簡體   English   中英

MongoDB 一次查詢多個collections

[英]MongoDB query 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"
}

這是我的 mongodb 中的示例。我想獲取所有“via”屬性等於“facebook”並由管理員 (“admin”:1) 發布的帖子。 我不知道如何獲取此查詢。 由於 mongodb 不是關系型數據庫,所以無法進行連接操作。 有什么解決辦法?

嘗試加入 MongoDB 會破壞使用 MongoDB 的目的。 但是,您可以使用DBref並編寫應用程序級代碼(或庫),以便它自動為您獲取這些引用。

或者您可以更改您的架構並使用嵌入式文檔

您的最終選擇是保持原樣並執行兩個查詢。

您可以使用$lookup (multiple) 從多個 collections 中獲取記錄:

例子:

如果您有更多 collections(我這里有 3 個 collections 用於演示,您可以有 3 個以上)。 我想從單個 object 中的 3 collections 獲取數據:

集合如下:

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

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

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

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

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

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

如果您想要來自每個 collections 的所有記錄,那么您應該從查詢中刪除以下行:

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

這是您的問題的答案。

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

        }}

])

或者,您可以使用 go 和 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 中提到的,你不能在 collections 之間加入。

對於您的示例,解決方案可能是:

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

執行多個查詢或使用嵌入式文檔或查看“數據庫引用”。

一種解決方案:將 isAdmin: 0/1 標志添加到您的帖子收集文檔中。

其他解決方案:使用 DBrefs

您可以編寫如下示例 JavaScript 並在需要時調用 function。

請參考以下位置的插圖: 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() 調用它,如圖所示。

發布是因為我想壓平合並的文檔,而不是其他答案生成的分層文檔。

要將多個 collections 合並到一個平面單個文檔中,請查看 Mongo 文檔中的 $lookup with $mergeObjects: https://docs.mongodb.com/manual/reference/operator/aggregation/lookup/#use--lookup-with--合並對象

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM