Program Tip

MongoDB는 한 번에 여러 컬렉션 쿼리

programtip 2020. 11. 21. 09:27
반응형

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의 샘플입니다. "페이스 북"과 같은 "경유"속성이 있고 관리자 ( "관리자": 1)에 의해 게시 된 모든 게시물을 얻고 싶습니다. 이 쿼리를 얻는 방법을 알 수 없습니다. mongodb는 관계형 데이터베이스가 아니기 때문에 조인 작업을 할 수 없습니다. 해결책은 무엇일까요?


MongoDB에서 JOIN을 시도하면 MongoDB 사용 목적이 무효화됩니다. 그러나 DBref를 사용하고 이러한 참조를 자동으로 가져 오도록 애플리케이션 수준 코드 (또는 라이브러리)를 작성할 수 있습니다.

또는 스키마를 변경하고 포함 된 문서를 사용할 수 있습니다 .

최종 선택은 현재 상태 그대로두고 두 가지 쿼리를 수행하는 것입니다.


귀하의 질문에 대한 답변입니다.

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

$lookup(multiple)을 사용 하여 여러 컬렉션에서 레코드를 가져올 수 있습니다 .

예:

더 많은 컬렉션이있는 경우 (여기 데모 용 컬렉션이 3 개 있습니다. 3 개 이상있을 수 있습니다). 단일 개체의 3 개 컬렉션에서 데이터를 가져오고 싶습니다.

컬렉션은 다음과 같습니다.

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

각 컬렉션의 모든 레코드를 원하는 경우 쿼리에서 아래 줄을 제거해야합니다.

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

이전에 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/

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.

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

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


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

Other solution: use DBrefs


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

Do refer the illustration at : 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.

참고URL : https://stackoverflow.com/questions/6502541/mongodb-query-multiple-collections-at-once

반응형