2017-03-06 224 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") 
       } 
      ] 
     } 
    ] 
}