복붙노트

[MONGODB] 배열에 ObjectId가의에 조회 $

MONGODB

배열에 ObjectId가의에 조회 $

하며 Object의 배열이 하나의 ObjectId가보다는있는 필드에 $ 조회를 수행하는 구문은 무엇입니까?

예 주문 문서 :

{
  _id: ObjectId("..."),
  products: [
    ObjectId("..<Car ObjectId>.."),
    ObjectId("..<Bike ObjectId>..")
  ]
}

작동하지 않음 검색어 :

db.orders.aggregate([
    {
       $lookup:
         {
           from: "products",
           localField: "products",
           foreignField: "_id",
           as: "productObjects"
         }
    }
])

원하는 결과

{
  _id: ObjectId("..."),
  products: [
    ObjectId("..<Car ObjectId>.."),
    ObjectId("..<Bike ObjectId>..")
  ],
  productObjects: [
    {<Car Object>},
    {<Bike Object>}
  ],
}

해결법

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

    1.은 $ 조회 집계 파이프 라인 단계는 배열을 직접 작동하지 않습니다. A가 가능한 관련 데이터 (또는 정말 "조회") 가입의 "한 많은이"형식으로 "왼쪽 가입"을 위해 디자인의 주요 목적이다. 그러나이 값 배열을 특이 것으로 의도되지 않는다.

    은 $ 조회 집계 파이프 라인 단계는 배열을 직접 작동하지 않습니다. A가 가능한 관련 데이터 (또는 정말 "조회") 가입의 "한 많은이"형식으로 "왼쪽 가입"을 위해 디자인의 주요 목적이다. 그러나이 값 배열을 특이 것으로 의도되지 않는다.

    그러므로 반드시 먼저 이전 작업이 순서에 $ 조회 작업을 수행하는 "드 정상화"내용. 그리고 수단은 $ 언 와인드를 사용하는 것을 :

    db.orders.aggregate([
        // Unwind the source
        { "$unwind": "$products" },
        // Do the lookup matching
        { "$lookup": {
           "from": "products",
           "localField": "products",
           "foreignField": "_id",
           "as": "productObjects"
        }},
        // Unwind the result arrays ( likely one or none )
        { "$unwind": "$productObjects" },
        // Group back to arrays
        { "$group": {
            "_id": "$_id",
            "products": { "$push": "$products" },
            "productObjects": { "$push": "$productObjects" }
        }}
    ])
    

    $ 조회는 각 배열 구성원과 일치 한 후 다시 언 와인드 $ 및 $에서 $ 그룹이 최종 결과를 새로운 배열을 밀어 그래서 결과는, 배열 자체입니다.

    어떤 주어진 제품의 "productObjects"에 대한 하늘의 배열을 만듭니다 발견하고, 따라서 두 번째 $의 언 와인드가 호출되는 "제품"요소에 대한 문서를 부정하지 않는 일치 "왼쪽 가입"합니다.

    배열에 직접 응용 프로그램이 좋은 것입니다 만, 이것이 현재 가능한 많은에 특이 값을 일치시켜 작동하는 단지 방법입니다.

    $ 조회가 기본적으로 아주 새로운, 그것은 현재 .populate () 메소드의 "가난한 망 버전"으로 몽구스 잘 알고있는 사람들에게 친숙한 존재가 제공하는 것처럼 작동합니다. 인 차이 그 처리 $ 조회 이벤트 "서버 측"는 클라이언트에 반대하고 "가입"$ 조회에서 "성숙"의 일부는 현재 () .populate 것과 같은 조회를 보간과 같은 제안을 (부족한 것을 직접)에 배열.

    이 때문에 일부 운이 곧 후 다음 릴리스 또는 하나를 명중 것, 실제로 개선 SERVER-22881에 대한 할당 문제입니다.

    디자인 원리로서, 현재의 구조가 좋은, 나쁜,하지만 오버 헤드 단지 대상이 하나가 "가입"창조도 아니다. 당신은 데이터를 라이브 한 컬렉션 "사전에 합류", "수"경우에 따라서, 처음에 MongoDB를의 기본 서 원칙을 적용, 그것은 그렇게하는 것이 최선입니다.

    원칙적으로 $ 조회라고 할 수있는 하나 개의 다른 점은 여기에 표시된 것보다 여기에 "참여"의 의도가 주변의 다른 방식으로 작동하는 것입니다. "관련 문서"는 "부모"에 대한 참조를 포함 할 경우 그래서 오히려 "부모"문서에 다른 문서의 "관련 ID를"유지하는 것보다, 가장 적합한 일반 원칙이다.

    그래서 $ 조회는 몽구스 .populate 같은 () 수행 그것의 클라이언트 측 조인 방법의 역입니다 "관련 디자인"과 "일 최고"라고 할 수 있습니다. 대신 각 "많은"내 "을"idendifying함으로써, 당신은 먼저 배열을 언 와인드 $ 할 필요없이 관련 항목에서 빼냅니다.

  2. ==============================

    2.$ 조회 집계 파이프 라인 단계 지금에 (배열을 직접 작동 3.3.4 버전).

    $ 조회 집계 파이프 라인 단계 지금에 (배열을 직접 작동 3.3.4 버전).

    참조 : 룩업 값 외국 (인) 값의 로컬 (다중) 어레이 사이

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

    3.또한 하위 배열에 검사를 수행하기 위해 파이프 라인 단계를 사용할 수 있습니다

    또한 하위 배열에 검사를 수행하기 위해 파이프 라인 단계를 사용할 수 있습니다

    여기에 (미안 해요 뱀 사람이야) 파이썬을 사용하는 예입니다.

    db.products.aggregate([
      { '$lookup': {
          'from': 'products',
          'let': { 'pid': '$products' },
          'pipeline': [
            { '$match': { '$expr': { '$in': ['$_id', '$$pid'] } } }
            // Add additional stages here 
          ],
          'as':'productObjects'
      }
    ])
    

    여기 캐치 ObjectId가 배열 (현지 필드 / 소품 제품에 외국 _id)에있는 모든 개체와 일치하는 것입니다.

    또한 청소 또는 위의 주석으로 표시된 바와 같이, 추가 단계로 외국 기록을 투사 할 수 있습니다.

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

    4.대신 객체의 배열의 첫 번째 개체를 얻을 것이다 긴장을 풀고 $를 사용

    대신 객체의 배열의 첫 번째 개체를 얻을 것이다 긴장을 풀고 $를 사용

    질문:

    db.getCollection('vehicles').aggregate([
      {
        $match: {
          status: "AVAILABLE",
          vehicleTypeId: {
            $in: Array.from(newSet(d.vehicleTypeIds))
          }
        }
      },
      {
        $lookup: {
          from: "servicelocations",
          localField: "locationId",
          foreignField: "serviceLocationId",
          as: "locations"
        }
      },
      {
        $unwind: "$locations"
      }
    ]);
    

    결과:

    {
        "_id" : ObjectId("59c3983a647101ec58ddcf90"),
        "vehicleId" : "45680",
        "regionId" : 1.0,
        "vehicleTypeId" : "10TONBOX",
        "locationId" : "100",
        "description" : "Isuzu/2003-10 Ton/Box",
        "deviceId" : "",
        "earliestStart" : 36000.0,
        "latestArrival" : 54000.0,
        "status" : "AVAILABLE",
        "accountId" : 1.0,
        "locations" : {
            "_id" : ObjectId("59c3afeab7799c90ebb3291f"),
            "serviceLocationId" : "100",
            "regionId" : 1.0,
            "zoneId" : "DXBZONE1",
            "description" : "Masafi Park Al Quoz",
            "locationPriority" : 1.0,
            "accountTypeId" : 0.0,
            "locationType" : "DEPOT",
            "location" : {
                "makani" : "",
                "lat" : 25.123091,
                "lng" : 55.21082
            },
            "deliveryDays" : "MTWRFSU",
            "timeWindow" : {
                "timeWindowTypeId" : "1"
            },
            "address1" : "",
            "address2" : "",
            "phone" : "",
            "city" : "",
            "county" : "",
            "state" : "",
            "country" : "",
            "zipcode" : "",
            "imageUrl" : "",
            "contact" : {
                "name" : "",
                "email" : ""
            },
            "status" : "",
            "createdBy" : "",
            "updatedBy" : "",
            "updateDate" : "",
            "accountId" : 1.0,
            "serviceTimeTypeId" : "1"
        }
    }
    
    
    {
        "_id" : ObjectId("59c3983a647101ec58ddcf91"),
        "vehicleId" : "81765",
        "regionId" : 1.0,
        "vehicleTypeId" : "10TONBOX",
        "locationId" : "100",
        "description" : "Hino/2004-10 Ton/Box",
        "deviceId" : "",
        "earliestStart" : 36000.0,
        "latestArrival" : 54000.0,
        "status" : "AVAILABLE",
        "accountId" : 1.0,
        "locations" : {
            "_id" : ObjectId("59c3afeab7799c90ebb3291f"),
            "serviceLocationId" : "100",
            "regionId" : 1.0,
            "zoneId" : "DXBZONE1",
            "description" : "Masafi Park Al Quoz",
            "locationPriority" : 1.0,
            "accountTypeId" : 0.0,
            "locationType" : "DEPOT",
            "location" : {
                "makani" : "",
                "lat" : 25.123091,
                "lng" : 55.21082
            },
            "deliveryDays" : "MTWRFSU",
            "timeWindow" : {
                "timeWindowTypeId" : "1"
            },
            "address1" : "",
            "address2" : "",
            "phone" : "",
            "city" : "",
            "county" : "",
            "state" : "",
            "country" : "",
            "zipcode" : "",
            "imageUrl" : "",
            "contact" : {
                "name" : "",
                "email" : ""
            },
            "status" : "",
            "createdBy" : "",
            "updatedBy" : "",
            "updateDate" : "",
            "accountId" : 1.0,
            "serviceTimeTypeId" : "1"
        }
    }
    
  5. ==============================

    5.$ 조회 및 후속 $ 그룹과 집계하면 노드 몽구스 또는 스키마에 몇 가지 힌트와 지원 라이브러리를 사용하고 당신은 그를 가져 오기 위해 .populate ()를 사용할 수 있습니다 (즉, 매체의 경우는 그리고) 그렇다면, 꽤 복잡 서류:

    $ 조회 및 후속 $ 그룹과 집계하면 노드 몽구스 또는 스키마에 몇 가지 힌트와 지원 라이브러리를 사용하고 당신은 그를 가져 오기 위해 .populate ()를 사용할 수 있습니다 (즉, 매체의 경우는 그리고) 그렇다면, 꽤 복잡 서류:

    var mongoose = require("mongoose"),
        Schema = mongoose.Schema;
    
    var productSchema = Schema({ ... });
    
    var orderSchema = Schema({
      _id     : Number,
      products: [ { type: Schema.Types.ObjectId, ref: "Product" } ]
    });
    
    var Product = mongoose.model("Product", productSchema);
    var Order   = mongoose.model("Order", orderSchema);
    
    ...
    
    Order
        .find(...)
        .populate("products")
        ...
    
  6. ==============================

    6.나는 우리가 $ 매치 단계로 서문 경우 우리가 ID를 배열로 $ 조회 작업을 할 수 있습니다, 동의해야합니다.

    나는 우리가 $ 매치 단계로 서문 경우 우리가 ID를 배열로 $ 조회 작업을 할 수 있습니다, 동의해야합니다.

    // 조회 결과 아이디 어레이를 대체 [(db.products.aggregate     {$ 일치 : {제품 : {$가 존재 : TRUE}}}     {         조회 $ {             에서 "제품"             localField : "제품"             foreignField : "_id"             로 : "productObjects"         }     } ])

    우리는 파이프 라인에 조회 결과를 전달하려는 경우는 더 복잡해진다. 하지만 다시 (이미 @ user12164에 의해 제안) 그렇게 할 수있는 방법이있다 :

    // 파이프 라인에 전달 조회 결과 아이디 어레이를 대체 [(db.products.aggregate     {$ 일치 : {제품 : {$가 존재 : TRUE}}}     {         조회 $ {             에서 "제품"              보자 {제품 : "$ 제품"},              파이프 라인 :                  {$ 일치 : {$ EXPR : {$에서 : [ "$ _id", "$$ 제품"]}}}                  {$ 프로젝트 : {_id : 0}} // 억제 _id              ],             로 : "productObjects"         }     } ])

  7. from https://stackoverflow.com/questions/34967482/lookup-on-objectids-in-an-array by cc-by-sa and MIT license