MongoDB requests multiple collections at once

users { "_id":"12345", "admin":1 }, { "_id":"123456789", "admin":0 } posts { "content":"Some content", "owner_id":"12345", "via":"facebook" }, { "content":"Some other content", "owner_id":"123456789", "via":"facebook" } 

Here is an example of my mongoba. I want to receive all messages with the attribute "through" equal to "facebook" and sent by the administrator ("admin": 1). I could not figure out how to get this request. Since mongodb is not a relational database, I could not perform the join operation. What could be the solution?

+49
collections join mongodb
Jun 28 2018-11-11T00:
source share
7 answers

By trying to JOIN in MongoDB, the goal of using MongoDB wins. However, you can use DBref and write your code (or library) at the application level so that it automatically extracts these links for you.

Or you can change your layout and use inline documents .

Your last choice is to leave things exactly as they are now and make two requests.

+37
Jun 28 2018-11-11T00:
source share

Here is the answer to your question.

 db.getCollection('users').aggregate([ {$match : {admin : 1}}, {$lookup: {from: "posts",localField: "_id",foreignField: "owner_id",as: "posts"}}, {$project : { posts : { $filter : {input : "$posts" , as : "post", cond : { $eq : ['$$post.via' , 'facebook'] } } }, admin : 1 }} ]) 

Or you can go with the mongodb group option.

 db.getCollection('users').aggregate([ {$match : {admin : 1}}, {$lookup: {from: "posts",localField: "_id",foreignField: "owner_id",as: "posts"}}, {$unwind : "$posts"}, {$match : {"posts.via":"facebook"}}, { $group : { _id : "$_id", posts : {$push : "$posts"} }} ]) 
+10
Oct 22 '16 at 4:50
source share

As mentioned earlier in MongoDB, you cannot LINK between collections.

For your example, the solution could be:

 var myCursor = db.users.find({admin:1}); var user_id = myCursor.hasNext() ? myCursor.next() : null; db.posts.find({owner_id : user_id._id}); 

See the reference guide - cursors section: http://es.docs.mongodb.org/manual/core/cursors/

Another solution would be to include users in message collection, but I think that for most web applications, user collection should be independent for security reasons. A user collection may have roles, permissions, etc.

 posts { "content":"Some content", "user":{"_id":"12345", "admin":1}, "via":"facebook" }, { "content":"Some other content", "user":{"_id":"123456789", "admin":0}, "via":"facebook" } 

and then:

 db.posts.find({user.admin: 1 }); 
+8
Nov 13 '13 at 12:57
source share

You can use $lookup (multiple) to get records from multiple collections:

Example:

If you have more collections (I have 3 collections for demonstration here, you may have more than 3). and I want to get data from 3 collections in one object:

The collection looks like this:

db.doc1.find () is pretty () ;.

 { "_id" : ObjectId("5901a4c63541b7d5d3293766"), "firstName" : "shubham", "lastName" : "verma" } 

db.doc2.find () is pretty () ;.

 { "_id" : ObjectId("5901a5f83541b7d5d3293768"), "userId" : ObjectId("5901a4c63541b7d5d3293766"), "address" : "Gurgaon", "mob" : "9876543211" } 

db.doc3.find () is pretty () ;.

 { "_id" : ObjectId("5901b0f6d318b072ceea44fb"), "userId" : ObjectId("5901a4c63541b7d5d3293766"), "fbURLs" : "http://www.facebook.com", "twitterURLs" : "http://www.twitter.com" } 

Your request will now look like this:

 db.doc1.aggregate([ { $match: { _id: ObjectId("5901a4c63541b7d5d3293766") } }, { $lookup: { from: "doc2", localField: "_id", foreignField: "userId", as: "address" } }, { $unwind: "$address" }, { $project: { __v: 0, "address.__v": 0, "address._id": 0, "address.userId": 0, "address.mob": 0 } }, { $lookup: { from: "doc3", localField: "_id", foreignField: "userId", as: "social" } }, { $unwind: "$social" }, { $project: { __v: 0, "social.__v": 0, "social._id": 0, "social.userId": 0 } } ]).pretty(); 

Then your result will be:

 { "_id" : ObjectId("5901a4c63541b7d5d3293766"), "firstName" : "shubham", "lastName" : "verma", "address" : { "address" : "Gurgaon" }, "social" : { "fbURLs" : "http://www.facebook.com", "twitterURLs" : "http://www.twitter.com" } } 

If you need all the entries from each collection, you should remove the line below from the query:

 { $project: { __v: 0, "address.__v": 0, "address._id": 0, "address.userId": 0, "address.mob": 0 } } { $project: { "social.__v": 0, "social._id": 0, "social.userId": 0 } } 

After deleting the code, you will get the full entry:

 { "_id" : ObjectId("5901a4c63541b7d5d3293766"), "firstName" : "shubham", "lastName" : "verma", "address" : { "_id" : ObjectId("5901a5f83541b7d5d3293768"), "userId" : ObjectId("5901a4c63541b7d5d3293766"), "address" : "Gurgaon", "mob" : "9876543211" }, "social" : { "_id" : ObjectId("5901b0f6d318b072ceea44fb"), "userId" : ObjectId("5901a4c63541b7d5d3293766"), "fbURLs" : "http://www.facebook.com", "twitterURLs" : "http://www.twitter.com" } } 
+6
Apr 27 '17 at 9:20
source share

Run a few queries or use embedded documents or see "database links."

+3
Jun 28 2018-11-11T00:
source share

One solution: add the adAdmin: 0/1 flag to your document after collection.

Another solution: use DBrefs

+2
Jun 28 2018-11-11T00:
source share

You can write a JavaScript example as shown below and call the function when required.

Refer to the illustration at: http://dbversity.com/mongodb-querying-multiple-collections-with-a-javascript/

 function colListQuery() { var tcol = new Array() tcol= db.getCollectionNames(); for(var i = 1; i < tcol.length ; i++) { query = "db." + tcol[i] + ".find()"; var docs= eval(query); docs.forEach( function(doc, index){ print( "Database_Name:", db, "Collection_Name:", tcol[i], "x_value:", doc.x, "_id:", doc._id) }); } } 

Then call it with colListQuery () when you require it, as shown in the illustration.

+1
Jan 20 '16 at 10:53 on
source share



All Articles