Is there a way to only limit the number of columns that one can select in a nested eager loading in Laravel?
Currently, I have 3 models that inter-relate. For instance, let's assume that we have the Publisher model, Authors model, and books model.
A publisher has a relationship with the Authors and the Authors have a relation with the book's models.
The Publisher model has columns like:
id
name
address
fax number
email address
The author's models contain:
id
name
address
email
published books
publishers_id
The books models contain:
id
title
authors_id
published_on
category
If I want to check the books that have been published by a given publication company: This is how I pull the records
$published_books::Publisher::with('authors.books')->take(1);
With this, I get a response like this:
"id" : 1,
"name" : "Longhorn Ke",
"address" : "14th Street",
"fax number" : "null",
"email_address" : "longhorn#mail.com",
"author" :{
"id" : 4,
"name" : patel,
"email" : patelguru#mail.com,
"published_books" : 12,
"publishers_id" : 1,
"books" : {
"id": 1,
"title" : "Art of life",
"authors_id" : 1,
"published_on" : "2020-07-12 14:22:25",
"category" : "Life teachings",
}
}
What I want is that when I load a book through the relationship I only want to get the name of the publisher, name of the author and the books details as shown below:
"id" : 1,
"name" : "Longhorn Ke",
"author" :{
"id" : 4,
"name" : patel,
"books" : {
"id": 1,
"title" : "Art of life",
"authors_id" : 1,
"published_on" : "2020-07-12 14:22:25",
"category" : "Life teachings",
}
}
How can I achieve that using eloquent? At this point, I understand that eloquent allows selection of specific columns on a nester load as shown in this link https://laravel.com/docs/master/eloquent-relationships#eager-loading-specific-columns but how do I do it in all the models to achieve the code result show above
For the top-most model you need select(); for the relationships you need relationship:id,...:
$published_books = Publisher::with(['authors.books', 'authors:id,name'])
->select('id', 'name')
->take(1);
Related
This question already has answers here:
How to Match on Joined Collections Using Laravel and MongoDB?
(1 answer)
How to join to two additional collections with conditions
(1 answer)
Aggregate $lookup Total size of documents in matching pipeline exceeds maximum document size
(2 answers)
Closed 4 years ago.
I have 2 collections in mongoDB namely product and author . Now the product collection has an object called the detail which has the title and other details whereas the author table has details regarding the author . Now i am trying to make a search that finds both title and author .. For eg: if the title is matched the details of that product should be listed and if the author is matched then again the details of that product should be shown. The author_id is a foreign_key in the product collection and the _id is a primary key in the author collection.
Below is my collection
The Product Collection
{
"_id" : ObjectId("5af2bd44a003533a8abf4e56"),
"product_type_id" : "5ae834807ae0d9538e45ab45",
"date_added" : "2018-03-12 12-3-54",
"status" : 1,
"detail" : {
"title" : "The random title",
"author_id" : "5af2c401a003533a8abf4e57",
"test_id" : 12345,
"description" : "I have a mongoDB collection with f rows",
"mrp" : 200,
"binding" : "sd",
"language" : "English",
"isbn" : NumberLong("9788700631625"),
"isbn_10" : 747532745,
"ean" : 897655,
"pages" : 200
}
}
This is the author collection
{
"_id" : ObjectId("5af2c401a003533a8abf4e57"),
"name" : "Dan Brown",
"test_id" : 12345
}
So far i have to search on the collections independently . But not together
For author search
db.author.aggregate
([{
"$match":
{
"name":"Dan Brown"
}
},
{
"$lookup":
{
"from": "product",
"localField": "test_id",
"foreignField": "detail.test_id",
"as": "users"
}
}
]
).pretty();
And title has been accessed using the normal find() method
EDIT 1:
So this is what i have tried so far. Is this the right approach . Btw it's still not working though
db.product.aggregate
(
[
{
"$match":
{
detail.title : 'The random title'
}
},
{
"$lookup":
{
"from": "author",
"localField": "test_id",
"foreignField": "detail.test_id",
"as": "tb2"
}
},
{
"$unwind": "$tb2"
},
{
"$match":
{
"tb2.name": "agent"
}
}
]
);
I try to use the Fractal library from The PHP League in my project
I have model: Object with fields id, name. It has relation prototypes as one to one.
So, model Prototype has relation Fields. Where model Fields contains fields: name, id.
Also there is separated model: ObjectFields that contains values for each object fields. For example:
object_id | value
1 1
In result I need to get output JSON:
objects : {
"id" : 1,
"name" : "Weapon",
"prototype": {
"id" : 1,
"name" : "Prototype Name",
"fields" : {
"field_name" : ObjectFields.value
}
}
}
Look please on
"fields" : {
"field_name" : ObjectFields.value
}
so, It would be field name as key and value from model ObjectFields.
Now I do request using query as:
Object::with("prototype.field.name.value");
It returns me nested output object, but I need that last 3 realations will be in one object by key field.name
I am using phalcon with mongodb. I have the following document in collection:
{
"_id" : ObjectId("547c8b6f7d30dd522b522255"),
"title" : "Test vacancy",
"slug" : "test-vacancy",
"location" : "the-netherlands",
"contract" : "fixed",
"function" : "Test vacancy",
"short_description" : "gdfsgfds",
"description" : "fdsafsdgfsdgdfa",
"promo_text" : "gfdsgdfs",
"company_name" : "gfdsgfsd",
"hits" : 36,
"updated_at" : 1.42685e+09,
}
In controller I am fetching all results by searched phase/query. For example I put example word and output will be all posts with example word in description or title or short_desc etc. Everything is correct but I want sort these posts in specific order. I mean if query will be same as title, this post should be first. Now it is somewhere below.
Can you help me? Thank you in advance.
I'm new to MongoDB and this is my first use of MapReduce ever.
I have two collections: Shops and Products with the following schema
Products
{'_id', 'type': 'first', 'enabled': 1, 'shop': $SHOP_ID }
{'_id', 'type': 'second', 'enabled': 0, 'shop': $SHOP_ID }
{'_id', 'type': 'second', 'enabled': 1, 'shop': $SHOP_ID }
And
Shops
{'_id', 'name':'L', ... }
{'_id', 'name':'M', ... }
I'm looking for a GROUPBY similar statement for MongoDB with MapReduce to retrieve the Shops with name 'L' that have Products with 'enabled' => 1
How can I do it? Thank you.
It should be possible to retrieve the desired information without a Map Reduce operation.
You could first query the "Products" collection for documents that match {'enabled': 1}, and then take the list of $SHOP_IDs from that query (which I imagine correspond to the _id values in the "Shops" collection), put them in an array, and perform an $in query on the "Shops" collection, combined with the query on "name".
For example, given the two collections:
> db.products.find()
{ "_id" : 1, "type" : "first", "enabled" : 1, "shop" : 3 }
{ "_id" : 2, "type" : "second", "enabled" : 0, "shop" : 4 }
{ "_id" : 3, "type" : "second", "enabled" : 1, "shop" : 5 }
> db.shops.find()
{ "_id" : 3, "name" : "L" }
{ "_id" : 4, "name" : "L" }
{ "_id" : 5, "name" : "M" }
>
First find all of the documents that match {"enabled" : 1}
> db.products.find({"enabled" : 1})
{ "_id" : 1, "type" : "first", "enabled" : 1, "shop" : 3 }
{ "_id" : 3, "type" : "second", "enabled" : 1, "shop" : 5 }
From the above query, generate a list of _ids:
> var c = db.products.find({"enabled" : 1})
> shop_ids = []
[ ]
> c.forEach(function(doc){shop_ids.push(doc.shop)})
> shop_ids
[ 3, 5 ]
Finally, query the shops collection for documents with _id values in the shop_ids array that also match {name:"L"}.
> db.shops.find({_id:{$in:shop_ids}, name:"L"})
{ "_id" : 3, "name" : "L" }
>
Similar questions regarding doing the equivalent of a join operation with Mongo have been asked before. This question provides some links which may provide you with additional guidance:
How to join MongoDB collections in Python?
If you would like to experiment with Map Reduce, here is a link to a blog post from a user who used an incremental Map Reduce operation to combine values from two collections.
http://tebros.com/2011/07/using-mongodb-mapreduce-to-join-2-collections/
Hopefully the above will allow you to retrieve the desired information from your collections.
Short answer: you can't do that (with a single MapReduce command).
Long answer: MapReduce jobs in MongoDB run only on a single collection and cannot refer other collections in the process. So, JOIN/GROUP BY-like behaviour of SQL is not available here. The new Aggregation Framework also operates on a single collection only.
I propose a two-part solution:
Get all shops with name "L".
Compose and run map-reduce command that will check every product document against this pre-computed list of shops.
Here are the objects:
courses
{ "name" : "Biology", "_id" : ObjectId("4b0552b0f0da7d1eb6f126a1") }
students
{
"name" : "Joe",
"classes" : [
{
"$ref" : "courses",
"$id" : ObjectId("4b0552b0f0da7d1eb6f126a1")
}
],
"_id" : ObjectId("4b0552e4f0da7d1eb6f126a2")
}
Using the PHP Mongo Class, how do I get all the students that has a biology course?
Thanks
You'll need to query twice. I dont have my environment in front of me, but something similar to what's below. I may have the "nested" portion of the second query incorrect.
// First grab the ID for the course.
$course = $collection->findOne(array("name" => "Biology"));
// Next query the students collection.
$collection->find(array("classes" => array("id" => $course['_id'])));