2016-07-11 3 views
1

기본적으로 "trashed"된 하위 문서와 하위 하위 문서를 필터링하려고합니다. 여기 내 스키마의 제거 다운 버전입니다 :

permitSchema = { 
    _id, 
    name, 
    ... 
    feeClassifications: [ 
    new Schema({ 
     _id, 
     _trashed, 
     name, 
     fees: [ 
     new Schema({ 
      _id, 
      _trashed, 
      name, 
      amount 
     }) 
     ] 
    }) 
    ], 
    ... 
} 

그래서 나는 feeClassifications으로 원하는 효과를 얻을 수 있어요. 그러나 나는 feeClassifications.fees에 대해서도 동일한 효과를 얻을 수있는 방법을 찾고자 애 쓰고 있습니다.

Permit.aggregate([ 
    { $match: { _id: mongoose.Types.ObjectId(req.params.id) }}, 
    { $project: { 
    _id: 1, 
    _name: 1, 
    feeClassifications: { 
     $filter: { 
     input: '$feeClassifications', 
     as: 'item', 
     cond: { $not: {$gt: ['$$item._trashed', null] } } 
     } 
    } 
    }} 
]) 

을하지만 또한 중첩 된 배열 fees를 필터링 할 :

그래서,이 원하는대로 작동합니다. I는 다음과 같은 몇 가지를 시도했다 :

mongodb docs 가장 가까운을 따르도록 보인다
Permit.aggregate([ 
    { $match: { _id: mongoose.Types.ObjectId(req.params.id) }}, 
    { $project: { 
    _id: 1, 
    _name: 1, 
    feeClassifications: { 
     $filter: { 
     input: '$feeClassifications', 
     as: 'item', 
     cond: { $not: {$gt: ['$$item._trashed', null] } } 
     }, 
     fees: { 
     $filter: { 
      input: '$fees', 
      as: 'fee', 
      cond: { $not: {$gt: ['$$fee._trashed', null] } } 
     } 
     } 
    } 
    }} 
]) 

. (여기

{ 
    "_id" : ObjectId("57803fcd982971e403e3e879"), 
    "_updated" : ISODate("2016-07-11T19:24:27.204Z"), 
    "_created" : ISODate("2016-07-09T00:05:33.274Z"), 
    "name" : "Single Event", 
    "feeClassifications" : [ 
     { 
      "_updated" : ISODate("2016-07-11T19:05:52.418Z"), 
      "_created" : ISODate("2016-07-11T17:49:12.247Z"), 
      "name" : "Event Type 1", 
      "_id" : ObjectId("5783dc18e09be99840fad29f"), 
      "fees" : [ 
       { 
        "_updated" : ISODate("2016-07-11T18:51:10.259Z"), 
        "_created" : ISODate("2016-07-11T18:41:16.110Z"), 
        "name" : "Basic Fee", 
        "amount" : 156.5, 
        "_id" : ObjectId("5783e84cc46a883349bb2339") 
       }, 
       { 
        "_updated" : ISODate("2016-07-11T19:05:52.419Z"), 
        "_created" : ISODate("2016-07-11T19:05:47.340Z"), 
        "name" : "Secondary Fee", 
        "amount" : 50, 
        "_id" : ObjectId("5783ee0bad7bf8774f6f9b5f"), 
        "_trashed" : ISODate("2016-07-11T19:05:52.410Z") 
       } 
      ] 
     }, 
     { 
      "_updated" : ISODate("2016-07-11T18:22:21.567Z"), 
      "_created" : ISODate("2016-07-11T18:22:21.567Z"), 
      "name" : "Event Type 2", 
      "_id" : ObjectId("5783e3dd540078de45bbbfaf"), 
      "_trashed" : ISODate("2016-07-11T19:24:27.203Z") 
     } 
    ] 
} 

그리고 원하는 출력입니다 : 이 this object is already an operator expression, and can't be used as a document expression (at 'fees')

업데이트 : ----------- 요청으로

, 여기에 샘플 문서의는하지만 오류를 얻을 "휴지통"하위 문서가) feeClassificationsfees BOTH에서 제외됩니다

{ 
    "_id" : ObjectId("57803fcd982971e403e3e879"), 
    "_updated" : ISODate("2016-07-11T19:24:27.204Z"), 
    "_created" : ISODate("2016-07-09T00:05:33.274Z"), 
    "name" : "Single Event", 
    "feeClassifications" : [ 
     { 
      "_updated" : ISODate("2016-07-11T19:05:52.418Z"), 
      "_created" : ISODate("2016-07-11T17:49:12.247Z"), 
      "name" : "Event Type 1", 
      "_id" : ObjectId("5783dc18e09be99840fad29f"), 
      "fees" : [ 
       { 
        "_updated" : ISODate("2016-07-11T18:51:10.259Z"), 
        "_created" : ISODate("2016-07-11T18:41:16.110Z"), 
        "name" : "Basic Fee", 
        "amount" : 156.5, 
        "_id" : ObjectId("5783e84cc46a883349bb2339") 
       } 
      ] 
     } 
    ] 
} 

답변

1

우리가 외부 및 inne 모두 필터링 할 때문에 r 배열 필드를 사용하여 우리가 원하는 "값"을 가진 배열을 반환하는 $map 변수 연산자를 사용할 수 있습니다.

$map 표현식에서는 논리적 인 $cond itional $filter을 사용하여 문서 및 하위 문서 배열 필드에서 일치하지 않는 문서를 제거합니다.

조건은 $lt이며 "_trashed"필드가 하위 문서 및 하위 문서 배열 필드에없는 경우 true를 반환합니다.

$cond 표현식에서 <false case>에 대해서도 false를 반환합니다. 물론 결과에 필터를 적용하여 모두 false을 제거해야합니다. 곧 MongoDB를 릴리스에서

Permit.aggregate(
    [ 
     { "$match": { "_id": mongoose.Types.ObjectId(req.params.id) } }, 
     { "$project": { 
      "_updated": 1, 
      "_created": 1, 
      "name": 1, 
      "feeClassifications": { 
       "$filter": { 
        "input": { 
         "$map": { 
          "input": "$feeClassifications", 
          "as": "fclass", 
          "in": { 
           "$cond": [ 
            { "$lt": [ "$$fclass._trashed", 0 ] }, 
            { 
             "_updated": "$$fclass._updated", 
             "_created": "$$fclass._created", 
             "name": "$$fclass.name", 
             "_id": "$$fclass._id", 
             "fees": { 
              "$filter": { 
               "input": "$$fclass.fees", 
               "as": "fees", 
               "cond": { "$lt": [ "$$fees._trashed", 0 ] } 
              } 
             } 
            }, 
            false 
           ] 
          } 
         } 
        }, 
        "as": "cls", 
        "cond": "$$cls" 
       } 
      } 
     }} 
    ] 
) 

(이 글을 쓰는과 MongoDB를 3.3.5 이후로), 당신은 $switch 표현으로하여 $map 표현의 $cond 표현을 대체 할 수

Permit.aggregate(
    [ 
     { "$match": { "_id": mongoose.Types.ObjectId(req.params.id) } }, 
     { "$project": { 
      "_updated": 1, 
      "_created": 1, 
      "name": 1, 
      "feeClassifications": { 
       "$filter": { 
        "input": { 
         "$map": { 
          "input": "$feeClassifications", 
          "as": "fclass", 
          "in": { 
           "$switch": { 
            "branches": [ 
             { 
              "case": { "$lt": [ "$$fclass._trashed", 0 ] }, 
              "then": { 
               "_updated": "$$fclass._updated", 
               "_created": "$$fclass._created", 
               "name": "$$fclass.name", 
               "_id": "$$fclass._id", 
               "fees": { 
                "$filter": { 
                 "input": "$$fclass.fees", 
                 "as": "fees", 
                 "cond": { "$lt": [ "$$fees._trashed", 0 ] } 
                } 
               } 
              } 
             } 
            ], 
            "default": false 
           } 
          } 
         } 
        }, 
        "as": "cls", 
        "cond": "$$cls" 
       } 
      } 
     }} 
    ] 
) 
+0

나는 너에게 충분히 감사 할 수 없었다! 유익한 답변과 설명에 감사드립니다. 이것은 나가 그것을 가치있어 혼자 이것을 파악하는 것을 시도하는 시간을한다! – Joao