MongoDB一次查询多个集合
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" }
这里是我的mongodb的一个例子。 我想获得所有具有“通过”属性等于“脸谱”,由pipe理员(“pipe理员”:1)张贴的职位。 我无法弄清楚如何获得这个查询。 由于mongodb不是关系型数据库,我无法进行连接操作。 什么可能是解决scheme?
尝试在MongoDB中join会破坏使用MongoDB的目的。 但是,您可以使用DBref并编写应用程序级代码(或库),以便自动为您提取这些引用。
或者你可以改变你的模式,并使用embedded式文件 。
你最后的select是把事情按现在的样子去做,然后做两个查询。
这是你的问题的答案。
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 }} ])
或者你也可以用mongodb组选项去。
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"} }} ])
正如之前在MongoDB中所提到的,你不能在集合之间join。
举个例子,解决scheme可能是:
var myCursor = db.users.find({admin:1}); var user_id = myCursor.hasNext() ? myCursor.next() : null; db.posts.find({owner_id : user_id._id});
请参阅参考手册 – 游标部分: http : //es.docs.mongodb.org/manual/core/cursors/
其他解决scheme是将用户embedded到posts集合中,但是我认为对于大多数Web应用程序来说,出于安全原因,用户集合需要是独立的。 用户集合可能包含angular色,权限等
posts { "content":"Some content", "user":{"_id":"12345", "admin":1}, "via":"facebook" }, { "content":"Some other content", "user":{"_id":"123456789", "admin":0}, "via":"facebook" }
接着:
db.posts.find({user.admin: 1 });
您可以使用$lookup
(multiple)从多个集合中获取logging:
例:
如果你有更多的collections(我有3个collections的演示在这里,你可以有超过3)。 我想从3个集合中获取单个对象的数据:
收集如下:
db.doc1.find()相当();
{ "_id" : ObjectId("5901a4c63541b7d5d3293766"), "firstName" : "shubham", "lastName" : "verma" }
db.doc2.find()相当();
{ "_id" : ObjectId("5901a5f83541b7d5d3293768"), "userId" : ObjectId("5901a4c63541b7d5d3293766"), "address" : "Gurgaon", "mob" : "9876543211" }
db.doc3.find()相当();
{ "_id" : ObjectId("5901b0f6d318b072ceea44fb"), "userId" : ObjectId("5901a4c63541b7d5d3293766"), "fbURLs" : "http://www.facebook.com", "twitterURLs" : "http://www.twitter.com" }
现在您的查询将如下所示:
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();
那么你的结果将是:
{ "_id" : ObjectId("5901a4c63541b7d5d3293766"), "firstName" : "shubham", "lastName" : "verma", "address" : { "address" : "Gurgaon" }, "social" : { "fbURLs" : "http://www.facebook.com", "twitterURLs" : "http://www.twitter.com" } }
如果你想从每个集合的所有logging,那么你应该从查询中删除下面的行:
{ $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 } }
删除上面的代码后,您将获得总logging为:
{ "_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" } }
执行多个查询或使用embedded式文档或查看“数据库引用”。
一个解决scheme:将isAdmin:0/1标志添加到您的后期收集文档。
其他解决scheme:使用DBrefs
你可以写下如下的示例JavaScript,并在需要时调用该函数。
请参考: 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) }); } }
然后在需要的时候用colListQuery()调用它,如图所示。