복붙노트

[MONGODB] 어떻게하여 MongoDB에서 참조 된 개체는 쿼리합니까?

MONGODB

어떻게하여 MongoDB에서 참조 된 개체는 쿼리합니까?

내 몽고 데이터베이스에 두 개의 컬렉션을 가지고, 그리고 FOOS는 하나 이상의 막대에 대한 참조를 포함 :

Foo: { 
  prop1: true,
  prop2: true,
  bars: [
     {
     "$ref": "Bar",
     "$id": ObjectId("blahblahblah")
     }
  ]
}

Bar: {
   testprop: true
}

내가 원하는 true로 테스트 소품 세트가 적어도 하나의 줄을 가지고있는 모든 음식을 찾는 것입니다. 나는이 명령을 해봤지만 결과가 반환되지 않습니다 :

db.Foo.find({ "bars.testprop" : { "$in": [ true ] } })

어떤 아이디어?

해결법

  1. ==============================

    1.이제 $ 조회를 사용 몽고 3.2에서 할 수 있습니다

    이제 $ 조회를 사용 몽고 3.2에서 할 수 있습니다

    $ 조회 사 개 인수를

    에서 : 지정 동일한 데이터베이스의 수집은 함께 결합 수행 할 수 있습니다. 로부터 수집 분산됩니다 할 수 없습니다.

    localField 다음 $ 조회 단계에 문서의 입력에서 지정 필드. 컬렉션에서의 문서에서 foreignField에 localField에 평등 경기 수행을 조회 $.

    컬렉션에서의 문서에서 지정을 필드 : foreignField.

    같이 지정 새로운 배열 필드의 이름은 입력 문서에 추가 할 수 있습니다. 새로운 배열 필드에서 수집에서 일치 된 문서를 포함한다.

    db.Foo.aggregate(
      {$unwind: "$bars"},
      {$lookup: {
        from:"bar",
        localField: "bars",
        foreignField: "_id",
        as: "bar"
    
       }},
       {$match: {
        "bar.testprop": true
       }}
    )
    
  2. ==============================

    2.당신은 할 수 없습니다. http://www.mongodb.org/display/DOCS/Database+References 참조

    당신은 할 수 없습니다. http://www.mongodb.org/display/DOCS/Database+References 참조

    당신은 클라이언트에서 수행해야합니다.

  3. ==============================

    3.우리는 엔티티의 몇 @Referenece를 사용하는 곳에 우리가 모르핀와 함께 MongoDB를 (3.4.4, 테스트를 위해 실제로 3.5.5)를 사용으로 우리는 비슷한 문제가 있었다. 우리는하지만이 솔루션이 행복하지 이러한 선언을 제거 고려하는 대신 수동으로 참조 조회를 않습니다.

    우리는 엔티티의 몇 @Referenece를 사용하는 곳에 우리가 모르핀와 함께 MongoDB를 (3.4.4, 테스트를 위해 실제로 3.5.5)를 사용으로 우리는 비슷한 문제가 있었다. 우리는하지만이 솔루션이 행복하지 이러한 선언을 제거 고려하는 대신 수동으로 참조 조회를 않습니다.

    즉 우리는 회사의 수집 및 사용자 컬렉션이 있습니다. 모르핀의 사용자 개체는 회사의 실체에 @Refrence 선언이 포함되어 있습니다. 각각의 회사 컬렉션과 같은 항목이 포함되어 있습니다

    /* 1 */
    {
        "_id" : ObjectId("59a92501df01110fbb6a5dee"),
        "name" : "Test",
        "gln" : "1234567890123",
        "uuid" : "f1f86961-e8d5-40bb-9d3f-fdbcf549066e",
        "creationDate" : ISODate("2017-09-01T09:14:41.551Z"),
        "lastChange" : ISODate("2017-09-01T09:14:41.551Z"),
        "version" : NumberLong(1),
        "disabled" : false
    }
    
    /* 2 */
    {
        "_id" : ObjectId("59a92501df01110fbb6a5def"),
        "name" : "Sample",
        "gln" : "3210987654321",
        "uuid" : "fee69ee4-b29c-483b-b40d-e702b50b0451",
        "creationDate" : ISODate("2017-09-01T09:14:41.562Z"),
        "lastChange" : ISODate("2017-09-01T09:14:41.562Z"),
        "version" : NumberLong(1),
        "disabled" : false
    }
    

    사용자 컬렉션 동안 다음 항목이 포함되어 있습니다

    /* 1 */
    {
        "_id" : ObjectId("59a92501df01110fbb6a5df0"),
        "userId" : "admin",
        "userKeyEncrypted" : {
            "salt" : "78e0528db239fd86",
            "encryptedAttribute" : "e4543ddac7cca9757721379e4e70567bb13956694f473b73f7723ac2e2fc5245"
        },
        "passwordHash" : "$2a$10$STRNORu9rcbq4qYUMld4G.HJk8QQQQBmAswSNC/4PBn2bih0BvjM6",
        "roles" : [ 
            "ADMIN"
        ],
        "company" : {
            "$ref" : "company",
            "$id" : ObjectId("59a92501df01110fbb6a5dee")
        },
        "uuid" : "b8aafdcf-d5c4-4040-a96d-8ab1a8608af8",
        "creationDate" : ISODate("2017-09-01T09:14:41.673Z"),
        "lastChange" : ISODate("2017-09-01T09:14:41.765Z"),
        "version" : NumberLong(1),
        "disabled" : false
    }
    
    /* 2 */
    {
        "_id" : ObjectId("59a92501df01110fbb6a5df1"),
        "userId" : "sample",
        "userKeyEncrypted" : {
            "salt" : "e3ac48695dea5f51",
            "encryptedAttribute" : "e804758b0fd13c219c3fc383eaa9267b70f7b8a1ed74f05575add713ce11804a"
        },
        "passwordHash" : "$2a$10$Gt2dq1vy4J9MeqDnXjokAOtvFcvbhe/g9wAENXFPaPxLAw1L4EULG",
        "roles" : [ 
            "USER"
        ],
        "company" : {
            "$ref" : "company",
            "$id" : ObjectId("59a92501df01110fbb6a5def")
        },
        "uuid" : "55b62d4c-e5ee-408d-80c0-b79e02085b02",
        "creationDate" : ISODate("2017-09-01T09:14:41.873Z"),
        "lastChange" : ISODate("2017-09-01T09:14:41.878Z"),
        "version" : NumberLong(1),
        "disabled" : false
    }
    
    /* 3 */
    {
        "_id" : ObjectId("59a92501df01110fbb6a5df2"),
        "userId" : "user",
        "userKeyEncrypted" : {
            "salt" : "ab9df671340a7d8b",
            "encryptedAttribute" : "7d8ad4ca6ad88686d810c70498407032f1df830596f72d931880483874d9cce3"
        },
        "passwordHash" : "$2a$10$0FLFw3ixW79JIBrD82Ly6ebOwnEDliS.e7GmrNkFp2nkWDA9OE/RC",
        "uuid" : "d02aef94-fc3c-4539-a22e-e43b8cd78aaf",
        "creationDate" : ISODate("2017-09-01T09:14:41.991Z"),
        "lastChange" : ISODate("2017-09-01T09:14:41.995Z"),
        "version" : NumberLong(1),
        "disabled" : false
    }
    

    특정 회사의 사용자보기를 만들려면 우리는 또한 사용자에 회사를 역 참조하고 싶었 필드 만 선택 등이 있습니다. "$$ ROOT.element"작업 기본적으로 키와 값 쌍에 주어진 요소의 필드를 분할 : 우리는 MongoDB를가 $ objectToArray를 제공하는 것을 알게 버그 리포트 내에서 의견을 바탕으로. $ objectToArray 작업이 MongoDB를 버전 3.4.4에서 추가되었다합니다!

    회사 요소의 집계는 다음과 같이 보일 수 있습니다 $ objectToArray 작업을 사용하여 사용자의 컬렉션에 포함 :

    dp.user.aggregate([{ 
        $project: { 
            "userId": 1, 
            "userKeyEncrypted": 1, 
            "uuid":1, 
            "roles": 1, 
            "passwordHash": 1, 
            "disabled": 1, 
            company: { $objectToArray: "$$ROOT.company" }
        } 
    }])
    

    이 같은 위의 집계 외모의 결과 :

    /* 1 */
    {
        "_id" : ObjectId("59a92501df01110fbb6a5df0"),
        "userId" : "admin",
        "userKeyEncrypted" : {
            "salt" : "78e0528db239fd86",
            "encryptedAttribute" : "e4543ddac7cca9757721379e4e70567bb13956694f473b73f7723ac2e2fc5245"
        },
        "passwordHash" : "$2a$10$STRNORu9rcbq4qYUMld4G.HJk8QQQQBmAswSNC/4PBn2bih0BvjM6",
        "roles" : [ 
            "ADMIN"
        ],
        "uuid" : "b8aafdcf-d5c4-4040-a96d-8ab1a8608af8",
        "disabled" : false,
        "company" : [ 
            {
                "k" : "$ref",
                "v" : "company"
            }, 
            {
                "k" : "$id",
                "v" : ObjectId("59a92501df01110fbb6a5dee")
            }
        ]
    }
    
    /* 2 */
    {
        "_id" : ObjectId("59a92501df01110fbb6a5df1"),
        "userId" : "sample",
        "userKeyEncrypted" : {
            "salt" : "e3ac48695dea5f51",
            "encryptedAttribute" : "e804758b0fd13c219c3fc383eaa9267b70f7b8a1ed74f05575add713ce11804a"
        },
        "passwordHash" : "$2a$10$Gt2dq1vy4J9MeqDnXjokAOtvFcvbhe/g9wAENXFPaPxLAw1L4EULG",
        "roles" : [ 
            "USER"
        ],
        "uuid" : "55b62d4c-e5ee-408d-80c0-b79e02085b02",
        "disabled" : false,
        "company" : [ 
            {
                "k" : "$ref",
                "v" : "company"
            }, 
            {
                "k" : "$id",
                "v" : ObjectId("59a92501df01110fbb6a5def")
            }
        ]
    }
    
    /* 3 */
    {
        "_id" : ObjectId("59a92501df01110fbb6a5df2"),
        "userId" : "user",
        "userKeyEncrypted" : {
            "salt" : "ab9df671340a7d8b",
            "encryptedAttribute" : "7d8ad4ca6ad88686d810c70498407032f1df830596f72d931880483874d9cce3"
        },
        "passwordHash" : "$2a$10$0FLFw3ixW79JIBrD82Ly6ebOwnEDliS.e7GmrNkFp2nkWDA9OE/RC",
        "uuid" : "d02aef94-fc3c-4539-a22e-e43b8cd78aaf",
        "disabled" : false,
        "company" : null
    }
    

    지금은 이미 설명 및 사용자 응답에 간접 참조 된 회사의 값을 복사 한 간단하게 (어떤 회사가 지정되지 가지고 즉 사용자를 오른쪽 배열 항목을 선택) 원치 않는 물건을 필터링 $ 조회 작업 @sidgate을 공급하기 위해의 문제이다.

    즉 하나 같이 응집 아래 조인 수행 조회에 정의 된 값으로 할당 같은 기업이 사용자에게 기업의 데이터를 추가한다 :

    db.user.aggregate([
        { $project: { "userId": 1, "userKeyEncrypted": 1, "uuid":1, "roles": 1, "passwordHash": 1, "disabled": 1, company: { $objectToArray: "$$ROOT.company" }} }, 
        { $unwind: "$company" }, 
        { $match: { "company.k": "$id"}  }, 
        { $lookup: { from: "company", localField: "company.v", foreignField: "_id", as: "company_data" } }
    ])
    

    위의 집계에 대한 결과는 아래에 볼 수있다 :

    /* 1 */
    {
        "_id" : ObjectId("59a92501df01110fbb6a5df0"),
        "userId" : "admin",
        "userKeyEncrypted" : {
            "salt" : "78e0528db239fd86",
            "encryptedAttribute" : "e4543ddac7cca9757721379e4e70567bb13956694f473b73f7723ac2e2fc5245"
        },
        "passwordHash" : "$2a$10$STRNORu9rcbq4qYUMld4G.HJk8QQQQBmAswSNC/4PBn2bih0BvjM6",
        "roles" : [ 
            "ADMIN"
        ],
        "uuid" : "b8aafdcf-d5c4-4040-a96d-8ab1a8608af8",
        "disabled" : false,
        "company" : {
            "k" : "$id",
            "v" : ObjectId("59a92501df01110fbb6a5dee")
        },
        "company_data" : [ 
            {
                "_id" : ObjectId("59a92501df01110fbb6a5dee"),
                "name" : "Test",
                "gln" : "1234567890123",
                "uuid" : "f1f86961-e8d5-40bb-9d3f-fdbcf549066e",
                "creationDate" : ISODate("2017-09-01T09:14:41.551Z"),
                "lastChange" : ISODate("2017-09-01T09:14:41.551Z"),
                "version" : NumberLong(1),
                "disabled" : false
            }
        ]
    }
    
    /* 2 */
    {
        "_id" : ObjectId("59a92501df01110fbb6a5df1"),
        "userId" : "sample",
        "userKeyEncrypted" : {
            "salt" : "e3ac48695dea5f51",
            "encryptedAttribute" : "e804758b0fd13c219c3fc383eaa9267b70f7b8a1ed74f05575add713ce11804a"
        },
        "passwordHash" : "$2a$10$Gt2dq1vy4J9MeqDnXjokAOtvFcvbhe/g9wAENXFPaPxLAw1L4EULG",
        "roles" : [ 
            "USER"
        ],
        "uuid" : "55b62d4c-e5ee-408d-80c0-b79e02085b02",
        "disabled" : false,
        "company" : {
            "k" : "$id",
            "v" : ObjectId("59a92501df01110fbb6a5def")
        },
        "company_data" : [ 
            {
                "_id" : ObjectId("59a92501df01110fbb6a5def"),
                "name" : "Sample",
                "gln" : "3210987654321",
                "uuid" : "fee69ee4-b29c-483b-b40d-e702b50b0451",
                "creationDate" : ISODate("2017-09-01T09:14:41.562Z"),
                "lastChange" : ISODate("2017-09-01T09:14:41.562Z"),
                "version" : NumberLong(1),
                "disabled" : false
            }
        ]
    }
    

    희망이 볼 수 있듯이 우리는 회사의 참조를 포함 된 두 명의 사용자가 두 사용자는 이제 응답의 전체 기업 데이터가 있습니다. 이제 추가 필터링은 키 / 값 도우미 제거에 적용 할 수 있으며, 원치 않는 데이터를 숨 깁니다.

    마지막 쿼리 우리는이 같은 외모를 내놓았다 :

    db.user.aggregate([
        { $project: { "userId": 1, "userKeyEncrypted": 1, "uuid":1, "roles": 1, "passwordHash": 1, "disabled": 1, company: { $objectToArray: "$$ROOT.company" }} }, 
        { $unwind: "$company" }, 
        { $match: { "company.k": "$id"}  }, 
        { $lookup: { from: "company", localField: "company.v", foreignField: "_id", as: "company_data" } },
        { $project: { "userId": 1, "userKeyEncrypted": 1, "uuid":1, "roles": 1, "passwordHash": 1, "disabled": 1,  "companyUuid": { $arrayElemAt: [ "$company_data.uuid", 0 ] } } }
    ])
    

    어느 마침내 원하는 표현을 반환합니다 :

    /* 1 */
    {
        "_id" : ObjectId("59a92501df01110fbb6a5df0"),
        "userId" : "admin",
        "userKeyEncrypted" : {
            "salt" : "78e0528db239fd86",
            "encryptedAttribute" : "e4543ddac7cca9757721379e4e70567bb13956694f473b73f7723ac2e2fc5245"
        },
        "passwordHash" : "$2a$10$STRNORu9rcbq4qYUMld4G.HJk8QQQQBmAswSNC/4PBn2bih0BvjM6",
        "roles" : [ 
            "ADMIN"
        ],
        "uuid" : "b8aafdcf-d5c4-4040-a96d-8ab1a8608af8",
        "disabled" : false,
        "companyUuid" : "f1f86961-e8d5-40bb-9d3f-fdbcf549066e"
    }
    
    /* 2 */
    {
        "_id" : ObjectId("59a92501df01110fbb6a5df1"),
        "userId" : "sample",
        "userKeyEncrypted" : {
            "salt" : "e3ac48695dea5f51",
            "encryptedAttribute" : "e804758b0fd13c219c3fc383eaa9267b70f7b8a1ed74f05575add713ce11804a"
        },
        "passwordHash" : "$2a$10$Gt2dq1vy4J9MeqDnXjokAOtvFcvbhe/g9wAENXFPaPxLAw1L4EULG",
        "roles" : [ 
            "USER"
        ],
        "uuid" : "55b62d4c-e5ee-408d-80c0-b79e02085b02",
        "disabled" : false,
        "companyUuid" : "fee69ee4-b29c-483b-b40d-e702b50b0451"
    }
    

    이 방법의 일부 최종 참고 :이 집계되지는 매우 빠르고, 슬프게도,하지만 적어도 그것은 일을 가져옵니다. 이것은 아마도 몇 가지 추가 unwindings가 필요할 수 있지만 원래 질문으로 나는 참조의 배열을 테스트하지 않았습니다.

    업데이트 : 더 언급 버그 위의 보고서에서 의견 라인에있는 데이터를 집계의 또 다른 방법은, 아래로 볼 수 있습니다 :

    db.user.aggregate([
        { $project: { "userId": 1, "userKeyEncrypted": 1, "uuid":1, "roles": 1, "passwordHash": 1, "disabled": 1, companyRefs: { $let: { vars: { refParts: { $objectToArray: "$$ROOT.company" }}, in: "$$refParts.v" } } } },
        { $match: { "companyRefs": { $exists: true } } },
        { $project: { "userId": 1, "userKeyEncrypted": 1, "uuid":1, "roles": 1, "passwordHash": 1, "disabled": 1, "companyRef": { $arrayElemAt: [ "$companyRefs", 1 ] } } },
        { $lookup: { from: "company", localField: "companyRef", foreignField: "_id", as: "company_data" } },
        { $project: { "userId": 1, "userKeyEncrypted": 1, "uuid":1, "roles": 1, "passwordHash": 1, "disabled": 1,  "companyUuid": { $arrayElemAt: [ "$company_data.uuid", 0 ] } } }
    ])
    

    여기서 $ 보자 {바르 ...에 ...} 동작에 복사 자신의 개체에 대한 언급이 키 값은 따라서 나중에 대응 동작을 통해 기준을 조회에 있습니다.

    더 좋은 방법은 프로파일 링 할 수있다이 집계가 수행하는 중.

  4. ==============================

    4.음 .. 당신이 testprop 모든 문서의 _id의 바 모델을 조회 할 수있다 : 사실, 다음 해당 _id의 배열 푸 모델에 찾기에 $ 및 채우기 바을하면 첫 번째 쿼리에서 가져온입니다 .. : P

    음 .. 당신이 testprop 모든 문서의 _id의 바 모델을 조회 할 수있다 : 사실, 다음 해당 _id의 배열 푸 모델에 찾기에 $ 및 채우기 바을하면 첫 번째 쿼리에서 가져온입니다 .. : P

    어쩌면 "클라이언트에서"로 계산 : 그냥 생각 P.

  5. ==============================

    5.그것은 이전에는 불가능했지만, 몽고의 개선은 우리가 매우 가까운 그것을 얻을 수 V3.4.

    그것은 이전에는 불가능했지만, 몽고의 개선은 우리가 매우 가까운 그것을 얻을 수 V3.4.

    당신은 몽고 조인 쿼리와 함께 할 수 있습니다. 코드는 다음과 같을 것이다 :

    const mongoose = require("mongoose");
    const joinQuery = require("mongo-join-query");
    
    joinQuery(
        mongoose.models.Foo,
        {
            find: { "bars.testprop": { $in: [true] } },
            populate: ["bars"]
        },
        (err, res) => (err ? console.log("Error:", err) : console.log("Success:", res.results))
    );
    

    장면은 뒤에 몽고 조인 쿼리에 가입 할 수있는 모델을 확인하려면 몽구스 스키마를 사용하고 조인을 수행 할 집계 파이프 라인 및 쿼리를 작성합니다.

    공개 : 나는 정확하게이 사용 사례를 해결하기 위해이 라이브러리를 썼다.

  6. from https://stackoverflow.com/questions/9621928/how-do-i-query-referenced-objects-in-mongodb by cc-by-sa and MIT license