2011-06-28 105 views
50
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的一个示例。我想获得所有具有“通过”属性等于“脸谱”和由管理员(“管理员”:1)发布的帖子。我无法弄清楚如何获得这个查询。由于mongodb不是关系数据库,因此我无法进行连接操作。什么可能是解决方案?MongoDB一次查询多个集合

回答

39

试图在MongoDB中加入会破坏使用MongoDB的目的。但是,您可以使用DBref并编写应用程序级代码(或库),以便它自动为您提取这些引用。

或者你可以改变你的模式并使用embedded documents

您的最终选择是让事情完全按照现在的样子进行,并执行两个查询。

+1

如何将一个去写两个查询此? –

+0

学说MongoDB ODM是处理这类事情的一个体面的库。然而,它只允许你通过一层引用来加入;您不能在引用内引用任何程度的语法缓冲。 – CommaToast

+1

MongoJS中的普通查询如何实现? – Pille

3

执行多个查询或使用嵌入式文档或查看“数据库引用”。

2

一个解决方案:将isAdmin:0/1标志添加到您的发布文档。

其他的解决方案:使用DBREFS

8

如MongoDB中前面提到的,你不能集合之间的连接。

对于示例的解决方案可能是:

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/

其他的解决办法是嵌入在帖子中收集的用户,但我想对于大多数Web应用程序出于安全原因,用户集合需要独立。收集的用户可能有角色,任何权限等

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 }); 
1

您可以如下编写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(),当你需要它,如在illustaration调用它。

13

这里是你的问题的答案。

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"} 
    }} 
]) 
+0

这是干什么的?这是查询还是将元数据添加到集合? – ViniciusPires

+1

$ lookup操作符自版本3.2起是新的,就像一个左外连接。请参阅https://docs.mongodb.com/manual/reference/operator/aggregation/lookup/ – almoraleslopez

8

您可以使用$lookup(多)从多个集合获取记录:

例子:

如果您有更多的集合(我有一个演示3个集在这里,你可以有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" 
    } 
} 

如果你想从每个集合,然后所有记录您应该从查询中删除以下行:

{ 
      $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 
      } 
    } 

去除上面的代码后,你会得到的总战绩:

{ 
    "_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" 
    } 
}