2017-10-17 3 views
0

반환 된 문서에 하위 문서가없는 쿼리 나 집계를 만들고 싶습니다. 주어진 필드가 하위 문서가 될 것임을 미리 알지 못합니다 (아니면 그냥 건너 뛸 때 프로젝션을 사용합니다). 그래서 예를 들어,이 같은 문서가있는 경우 :MongoDB 쿼리 또는 집계를 사용하여 하위 문서 건너 뛰기

내 쿼리가이 문서를 반환
{ 
    _id: 1, 
    field1: "a", 
    field2: "b", 
    field3: { 
    subfield1: "c", 
    subfield2: "d" 
    } 
} 

, 그것은 FIELD3를 건너 뛰거나, 뭔가 다른 (예를 들어, 문자열 = "field_is_an_object")와 FIELD3의 값을 대체 하나를.

앞서 언급했듯이 어떤 필드가 하위 문서 (또는 "개체"유형)인지 알 수 없습니다. $ redact 연산자는 내가 찾을 수있는 가장 가까운 연산자 였지만 작동 시키려면 구문을 이해할 수 없었습니다.

답변

0

당신은 당신이 원하는 것을 얻을 수 있습니다 적어도 두 가지 방법이 있습니다 :

:

첫번째는 매우 간결하고는, 그러나, 이해하기 조금 더 복잡하고 어렵 단 하나의 통합 단계를 필요

db.collection.aggregate({ 
    $replaceRoot: { // create a new top level document 
     "newRoot": { // ...which shall be 
      $arrayToObject: { // ...created from an array 
       $filter: { // ...that again should contain only those elements 
        input: { // ...from our input array 
         $objectToArray: "$$ROOT" // ...which is our respective top level document transformed into an array of key-value pairs 
        }, 
        cond: { // ...where 
         $ne: [ { $type: "$$this.v" }, "object" ] // ...the "v" (as in "value" field is not an object) 
        } 
       } 
      } 
     } 
    } 
}) 

내가 생각할 수있는 두 번째 방법은 스테이지를 단계별로 추가하여 이해하기 쉽습니다 (항상 집계 프레임 워크와 같이).

db.collection.aggregate({ 
    $project: { 
     "tmp": { // we create a temporary field 
      $objectToArray: "$$ROOT" // that contains our respective root document represented as an array of key-value pairs 
     } 
    } 
}, { 
    $unwind: "$tmp" // flatten the temporary array into multiple documents 
}, { 
    $match: { 
     "tmp.v": { $not: { $type: "object" } } // filter all documents out that we do not want in our result 
    } 
}, { 
    $group: { // group all documents together again 
     "_id": "$_id", // into one bucket per original document ("_id") 
     "tmp": { 
      $push: "$tmp" // and create an array with all the key-value pairs that have survived our $match stage 
     } 
    } 
}, { 
    $replaceRoot: { // create a new top level document... 
     "newRoot": { 
      $arrayToObject: "$tmp" // ...out of the data we have left in our array 
     } 
    } 
}) 
+0

감사의 말. 자세한 설명은 매우 도움이됩니다. 내 유일한 의견은 $ objectToArray 작업이 3.6에서 새롭고 3.6이 공식적으로 아직 릴리스되지 않았다는 것입니다. 최신 RC 3.6을 설치했는데 작동했습니다. –

+0

3.4에서 사용할 수 있습니다. https://docs.mongodb.com/manual/reference/operator/aggregation/objectToArray/ – dnickless

+0

글쎄, 당황 스럽네. 나는 3.4.0에 있었기 때문에 나를 위해 일하지 않았다. 나는 "3.6에서 추가했다"고 말한 것을 보았습니다. 그래서 그것이 제가 설치 한 것입니다. 문서에 명확하게 그것이 3.4.4에 추가되었다고되어 있지만. 다시 한번 감사드립니다. –