programing

MongoDB는 여러 컬렉션을 동시에 쿼리합니다.

closeapi 2023. 3. 22. 21:14
반응형

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 샘플이 있습니다.「facebook」과 같은 「via」속성을 가지고, 관리자(「admin」:1)가 투고하는 투고를 모두 취득하고 싶다.이 쿼리를 얻는 방법을 찾을 수 없었습니다.mongodb는 관계형 데이터베이스가 아니기 때문에 가입 조작을 할 수 없었습니다.해결책은 무엇일까요?

사용할 수 있습니다.$lookup( multiple ) 여러 컬렉션에서 레코드를 가져오려면 다음 절차를 수행합니다.

예:

더 많은 컬렉션이 있는 경우(여기 데모용 컬렉션은 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에서 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"}
    }}
])

MongoDB에서는 이전에도 언급했듯이 컬렉션 간에 JOIN을 할 수 없습니다.

예를 들어 다음과 같은 솔루션이 있습니다.

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/

다른 해결책은 사용자를 게시물 모음에 포함시키는 것이지만 대부분의 웹 응용 프로그램 모음은 보안상의 이유로 독립적일 필요가 있다고 생각합니다.사용자 컬렉션에 역할, 사용 권한 등이 있을 수 있습니다.

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 플래그 추가.

기타 솔루션: DBref 사용

병합된 문서를 평평하게 만들고 싶었기 때문에 다른 답변이 생성하는 계층화된 문서와 비교해서 게시합니다.

여러 컬렉션을 하나의 플랫 문서로 병합하려면 Mongo 문서에서 $mergeObjects: https://docs.mongodb.com/manual/reference/operator/aggregation/lookup/ #use-with-subjects $mergeObjects에 대한 $mergeObjects: https://docs.mongodb.com/manual/reference/operator/aggregation/lookup/ #use-with-subjects

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

반응형