MongoDB一次查询多个集合

时间:2011-06-28 06:39:39

标签: collections join 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的样本。我想获得所有帖子的“via”属性等于“facebook”并由admin发布(“admin”:1)。我无法弄清楚如何获取此查询。由于mongodb不是关系数据库,我无法进行连接操作。可能是什么解决方案?

7 个答案:

答案 0 :(得分:43)

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

或者您可以更改架构并使用embedded documents

您最后的选择是完全按照现在的方式保留事物并进行两次查询。

答案 1 :(得分:17)

以下是您的问题的答案。

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 group选项。

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

答案 2 :(得分:13)

您可以使用{ "_id" : ObjectId("5901a4c63541b7d5d3293766"), "firstName" : "shubham", "lastName" : "verma" } (多个)从多个集合中获取记录:

示例:

如果你有更多的收藏(我在这里有3个演示集合,你可以拥有3个以上)。我想从单个对象中获取3个集合中的数据:

该集合如下:

<强> db.doc1.find()相当();

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

<强> db.doc2.find()相当();

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

<强> db.doc3.find()相当();

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

删除上述代码后,您将获得以下总记录:

$(document).ready(function(){

 $('#add').click(function(){
   $('html').append('<button class="btn">Test</button>');
 });
 $(document).on('click',".btn", function(){
   alert('clicked');
 });
});

答案 3 :(得分: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 });

答案 4 :(得分:3)

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

答案 5 :(得分:2)

一种解决方案:在帖子集合文档中添加isAdmin:0/1标志。

其他解决方案:使用DBrefs

答案 6 :(得分: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()调用它,如图所示。