2014-12-16 7 views
4

나는 몇 개의 필드가있는 문서를 가지고 있는데, 특히 배열 인 attrs이라는 필드가 있습니다. 집계 파이프 라인을 사용하고 있습니다.빈 배열을 사용하면 쿼리에 문서가 표시되지 않습니다.

내 쿼리에 요소가있는 경우 attrs (특성) 필드에 관심이 있습니다. 그렇지 않으면 결과를 얻고 싶습니다. 이 경우 해당 문서의 유형을 입력합니다.

문제는 문서가 attrs에에 필드를 모든 요소를 ​​포함하지 않는 경우 정말이 쿼리에서 원하는 것을 멀리 필터링됩니다 내가 자사의 _id.type 필드를 얻을 것입니다 .

{ 
    aggregate: "entities", 
    pipeline: [ 
     { 
      $match: { 
       _id.servicePath: { 
        $in: [ 
         /^/.*/, 
         null 
        ] 
       } 
      } 
     }, 
     { 
      $project: { 
       _id: 1, 
       "attrs.name": 1, 
       "attrs.type": 1 
      } 
     }, 
     { 
      $unwind: "$attrs" 
     }, 
     { 
      $group: { 
       _id: "$_id.type", 
       attrs: { 
        $addToSet: "$attrs" 
       } 
      } 
     }, 
     { 
      $sort: { 
       _id: 1 
      } 
     } 
    ] 
} 

그래서 질문은 : 나는 상관없이 그들이 그 (것)들이 경우에 속성을 포함한 바인드합니다을 가지고 있지만 모든 문서 유형을 포함하는 결과를 얻을 수있는 방법?

나는 그것이 의미가 있기를 바랍니다.

+1

당신은 샘플 examp와 함께 귀하의 게시물을 편집 할 수 있습니다하십시오 르 파일? – styvane

+0

빈 배열을 풀면 문서가 누락되어 문서를 추가 할 수 있습니다. – mallik

답변

4

당신은 마커로 사용할 수 있습니다 null 같은 자리이 문서가 어떤 attr 요소를 포함하지 않는 것을 나타냅니다 포함 하나 빈 attr 배열을 대체 할 $project 단계에서 $cond 연산자를 사용할 수 있습니다 .

그래서 당신은 $unwind 전에이 권리 같은 추가 $project 단계를 삽입 할 것 :

{ 
     $project: { 
      attrs: {$cond: { 
       if: {$eq: ['$attrs', [] ]}, 
       then: [null], 
       else: '$attrs' 
      }} 
     } 
    }, 

주의해야 할 점은 당신이 그의 최종 attrs 배열에 null 값으로 끝날 것이 오 그룹에 attrs 요소가없는 문서가 하나 이상 포함되어 있으므로 해당 클라이언트 측을 무시해야합니다. 귀하의 예제에서 하나가 유효하지 않기 때문에

예는 변경 $match 단계를 사용합니다.

입력 문서

[ 
    {_id: {type: 1, id: 2}, attrs: []}, 
    {_id: {type: 2, id: 1}, attrs: []}, 
    {_id: {type: 2, id: 2}, attrs: [{name: 'john', type: 22}, {name: 'bob', type: 44}]} 
] 

출력

{ 
    "result" : [ 
     { 
      "_id" : 1, 
      "attrs" : [ 
       null 
      ] 
     }, 
     { 
      "_id" : 2, 
      "attrs" : [ 
       { 
        "name" : "bob", 
        "type" : 44 
       }, 
       { 
        "name" : "john", 
        "type" : 22 
       }, 
       null 
      ] 
     } 
    ], 
    "ok" : 1 
} 

집계 명령

db.test.aggregate([ 
    { 
     $match: { 
      '_id.servicePath': { 
       $in: [ 
        null 
       ] 
      } 
     } 
    }, 
    { 
     $project: { 
      _id: 1, 
      "attrs.name": 1, 
      "attrs.type": 1 
     } 
    }, 
    { 
     $project: { 
      attrs: {$cond: { 
       if: {$eq: ['$attrs', [] ]}, 
       then: [null], 
       else: '$attrs' 
      }} 
     } 
    }, 
    { 
     $unwind: "$attrs" 
    }, 
    { 
     $group: { 
      _id: "$_id.type", 
      attrs: { 
       $addToSet: "$attrs" 
      } 
     } 
    }, 
    { 
     $sort: { 
      _id: 1 
     } 
    } 
]) 
+1

감사! 그것은 매력처럼 일했습니다! 참고 사항 : MongoDB 2.4를 사용하고 있으므로 $ cond 값은 객체 대신 배열이어야합니다. – LeandroGuillen

-1

일부 if 문과 루프를 사용하십시오.

먼저 문의 사항은 모두 문서를 먼저 선택해야합니다.

다음 그들 모두를 통해

루프, 속성의 수는 0보다 큰 경우, 속성을 반복. 유용하다고 생각되는 배열이나 출력으로 루프를 반복하십시오.

if 문을 사용하면 원하는 경우 결과를 삭제할 수 있습니다.

+0

그럴 수도 있겠지만, 어쩌면 집계 프레임 워크를 사용하여 문제를 해결할 수 있을지 궁금합니다. – fgalan

+1

대답 주셔서 감사합니다.하지만 fgalan이 모든 것을 내 편으로 끌어 들이지 않고 해결할 수 있다면 정말 좋을 것이라고 말했습니다. – LeandroGuillen

-1

'$ or'연산자와 두 개의 별도의 쿼리를 사용해야합니다. 하나는 attr 값이 필수 값이고 다른 하나는 attr이 null이거나 attr 키가없는 문서와 일치하는 쿼리입니다 $exists 연산자)

관련 문제