mongodb MongoDB一次查询多个集合

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6502541/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 12:08:30  来源:igfitidea点击:

MongoDB query multiple collections at once

collectionsjoinmongodb

提问by Sarpdoruk Tahmaz

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 a sample from my mongodb. I want to get all the posts which has "via" attribute equal to "facebook" and posted by an admin ("admin":1). I couldn't figure out how to acquire this query. Since mongodb is not a relational database, I couldn't do a join operation. What could be the solution ?

这是我的 mongodb 中的一个示例。我想获取所有具有“via”属性等于“facebook”并由管理员(“admin”:1)发布的帖子。我无法弄清楚如何获取此查询。由于 mongodb 不是关系型数据库,我无法进行连接操作。解决办法是什么?

采纳答案by Charles Hooper

Trying to JOIN in MongoDB would defeat the purpose of using MongoDB. You could, however, use a DBrefand write your application-level code (or library) so that it automatically fetches these references for you.

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

Or you could alter your schema and use embedded documents.

或者您可以更改架构并使用嵌入式文档

Your final choice is to leave things exactly the way they are now and do two queries.

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

回答by Shubham Verma

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

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

Example:

例子:

If you have more collections ( I have 3 collections for demo here, you can have more than 3 ). and I want to get the data from 3 collections in single object:

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

The collection are as:

合集如下:

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

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

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

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

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

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

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

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

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

Now your query will be as below:

现在您的查询将如下所示:

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 want all records from each collections then you should remove below line from 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 removing above code you will get total record as:

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

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

回答by Anish Agarwal

Here is answer for 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 either you can go with mongodb group option.

或者您可以使用 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"}
    }}
])

回答by almoraleslopez

As mentioned before in MongoDB you can't JOIN between collections.

正如之前在 MongoDB 中提到的,你不能在集合之间加入。

For your example a 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 manual - cursors section: http://es.docs.mongodb.org/manual/core/cursors/

请参阅参考手册 - 游标部分:http: //es.docs.mongodb.org/manual/core/cursors/

Other solution would be to embed users in posts collection, but I think for most web applications users collection need to be independent for security reasons. Users collection might have Roles, permissons, etc.

其他解决方案是将用户嵌入帖子集合中,但我认为对于大多数 Web 应用程序,出于安全原因,用户集合需要是独立的。用户集合可能有角色、权限等。

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

回答by Andreas Jung

Perform multiple queries or use embedded documents or look at "database references".

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

回答by kheya

One solution: add isAdmin: 0/1 flag to your post collection document.

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

Other solution: use DBrefs

其他解决方案:使用 DBrefs

回答by dbversity

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

您可以编写如下示例 JavaScript 并在需要时调用该函数。

Do refer the illustration at : http://dbversity.com/mongodb-querying-multiple-collections-with-a-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) });

}
}

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

然后在需要时使用 colListQuery() 调用它,如图所示。