2017-03-06 381 views
2

我如何找到位置3上的$匹配的文檔(只有數組「ndr」中的最後一項)。聚合搜索只需要在ndr的最後一個數組項中進行搜索。mongodb聚合嵌套嵌套數組

{ 
    "_id" : ObjectId("58bd5c63a3d24b4a2e4cde03"), 
    "name" : "great document", 
    "country" : "us_us", 
    "cdate" : ISODate("2017-03-06T12:56:03.405Z"), 
    "nodes" : [ 
     { 
      "node" : 3244343, 
      "name" : "Best Node ever", 
      "ndr" : [ 
       { 
        "position" : 7, 
        "cdate" : ISODate("2017-03-06T10:55:20.000Z") 
       }, 
       { 
        "position" : 3, 
        "cdate" : ISODate("2017-03-06T10:55:20.000Z") 
       } 
      ] 
     } 
    ], 
} 

我需要聚集

{ 
    "name" : "great document", 
    "country" : "us_us", 
    "cdate" : ISODate("2017-03-06T12:56:03.405Z"), 
    "nodes" : [ 
     { 
      "node" : 3244343, 
      "name" : "Best Node ever", 
      "ndr" : [ 
       { 
        "position" : 3, 
        "cdate" : ISODate("2017-03-06T10:55:20.000Z") 
       } 
      ] 
     } 
    ] 
} 

後,這樣的結果,我希望有人能幫助我。

+0

Josch大家好,歡迎堆棧溢出。你可以[編輯]你的問題,以顯示你到目前爲止已經嘗試了什麼,以及它出了什麼問題? –

+0

什麼是您的MongoDB服務器版本? – chridam

+0

我有版本的MongoDB版本3.4 – Josch

回答

0

您可以嘗試下面的Mongo 3.4版本的聚合。

的下面查詢查找使用$arrayElemAt操作者的ndr陣列中的最後一個項目(-1)並使用last可變$let操作者爲每個nodes和使用$$符號的last可變position值比較3存儲幷包裝陣列內的nbr元件[]如果找到條目並返回空數組。

$map經營者達成的nodes陣列內nbr陣列和項目更新nbr陣列,同時在映射nodes場的其餘部分。

$addFields階段將覆蓋現有的nodes與新的nodes,同時保持所有其他領域。

db.collection.aggregate([{ 
    $addFields: { 
     nodes: { 
      $map: { 
       input: "$nodes", 
       as: "value", 
       in: { 
        node: "$$value.node", 
        name: "$$value.name", 
        ndr: { 
         $let: { 
          vars: { 
           last: { 
            $arrayElemAt: ["$$value.ndr", -1] 
           } 
          }, 
          in: { 
           $cond: [{ 
             $eq: ["$$last.position", 3] 
            }, 
            ["$$last"], 
            [] 
           ] 
          } 
         } 
        } 
       } 
      } 
     } 
    } 
}]); 

更新:

你可以嘗試$redact這將讓整個文件,如果它發現從給定的過濾器匹配的位置。

$map以項目爲主的過濾器對每個節點nbr位置值和$anyElementTrue將檢查每個文檔前一個布爾值,並返回一個truefalse價值$redact將使用來自booelan值上truefalse值以上比較;保留真值和刪除文檔的錯誤值。

db.collection.aggregate([{ 
    $redact: { 
     $cond: [{ 
      $anyElementTrue: { 
       $map: { 
        input: "$nodes", 
        as: "value", 
        in: { 
         $let: { 
          vars: { 
           last: { 
            $arrayElemAt: ["$$value.ndr", -1] 
           } 
          }, 
          in: { 
           $cond: [{ 
             $eq: ["$$last.position", 3] 
            }, 
            true, 
            false 
           ] 
          } 
         } 
        } 
       } 
      } 
     }, "$$KEEP", "$$PRUNE"] 
    } 
}]); 
+0

Thx!如果不是nodes.node.position與給定的過濾器匹配,我如何刪除整個文檔?目前文件將在管道中。 – Josch

+0

添加了一個單獨的解決方案,將刪除文檔。 – Veeram

+0

完美的作品!謝謝! – Josch

0

您將需要展開兩個嵌套數組。

db.<collection>.aggregate([ 
     { $unwind: '$nodes' }, 
     { $unwind: '$nodes.ndr'}, 
     { $group: {'_id':{'_id':'$_id', 'nodeID', '$nodes.node' }, 
       'name':{'$last':'$name'}, 
       'country':{'$last':'$country'}, 
       'cdate':{'$last':'$cdate'}, 
       'nodes':{'$last':'$nodes'} 
       } 
     }, 
     { $match : { nodes.ndr.position: 3 } } 
    ]); 

從這裏您可以重新彙編帶有$組的聚合結果並進行投影。我不確定你的最終結果應該是什麼。

+0

以及如何我只能在最後一個數組項目中搜索? – Josch

+0

對不起,我認爲你正在尋找一個特定的價值「位置:3」,如果你需要找到最後你將需要使用一個$組和$最後一個https://docs.mongodb.com/manual/reference/operator/聚合/最後/ – Woodsy

+0

嗨,我需要找到最後一個數組項目 – Josch

0

Woodsy的解決方案非常適合我。現在我需要計算每個節點的$ avg,並計算從「node.bsr.rank」以百分比(loos或win)輸入的給定數量的最後日期。

像這樣的結果

{ 
    "name" : "great document", 
    "country" : "us_us", 
    "cdate" : ISODate("2017-03-06T12:56:03.405Z"), 
    "nodes" : [ 
     { 
      "node" : 3244343, 
      "name" : "Best Node ever", 
      "avg_rank": 4, 
      "historie": 120, 
      "ndr" : [ 
       { 
        "position" : 3, 
        "cdate" : ISODate("2017-03-06T10:55:20.000Z") 
       } 
      ] 
     } 
    ] 
}