2016-02-09 99 views
1

過濾數組元素的領域考慮下面的模式:

{ 
    "_id" : ObjectId("56b9bfb962debd68f8b61340"), 
    "Name" : "Parent", 
    "Children" : [ 
     { 
      "Name" : "A", 
      "Age" : NumberInt(0) 
     }, 
     { 
      "Name" : "B", 
      "Age" : NumberInt(1) 
     }, 
     { 
      "Name" : "C", 
      "Age" : NumberInt(2) 
     } 
    ] 
} 

我使用2 $項目階段。 1過濾「孩子」,另一個選擇除「Children.Age」字段:

db.collection.aggregate(
    [ 
    { 
     $project: { 
     Name: 1, 
     Children: { $filter: { 
      input: "$Children", 
      as: "child", 
      cond: { $gt: ["$$child.Age", 0] } 
     } } 
     } 
    }, 
    { 
     $project: { 
     Name: 1, 
     Children: { Name: 1 } 
     } 
    } 
    ] 
); 

我能做到只用1 $項目的階段呢?

我想避免使用$ unwind和$組,如果可能的話。

回答

1

是的,你可以縮短你的管道到一個階段。要做到這一點,您需要使用$map運營商。

db.collection.aggregate([ 
    { "$project": { 
     "Name": 1, 
     "children": { 
      "$map": { 
       "input": { 
        "$filter": { 
         "input": "$Children", 
         "as": "child", 
         "cond": { "$gt": [ "$$child.Age", 0 ] } 
        } 
       }, 
       "as": "ch", 
       "in": 
       "$$ch.Name" 
      } 
     } 
    }} 
]) 

另一種替代方法是使用$setDifference操作者和操作者$map操作者。但正如文檔中提到的:

$setDifference在結果中過濾出重複項以輸出僅包含唯一項的數組。

db.collection.aggregate([ 
    { "$project": { 
     "Name": 1, 
     "Children": { 
      "$setDifference": [ 
       { "$map": { 
        "input": "$Children", 
        "as": "child", 
        "in": { 
         "$cond": [ 
          { "$gt": [ "$$child.Age", 0 ] }, 
          "$$child.Name", 
          false 
         ] 
        } 
       }}, 
       [false] 
      ] 
     } 
    }} 
]) 

它返回:

{ 
     "_id" : ObjectId("56b9bfb962debd68f8b61340"), 
     "Name" : "Parent", 
     "Children" : [ 
       "B", 
       "C" 
     ] 
} 
+0

在第一解決方案:如果我whant排除1個領域,包括至少2個字段? –