【问题标题】:matching on _id after $group stage aggregation$group 阶段聚合后在 _id 上匹配
【发布时间】:2017-05-18 12:11:40
【问题描述】:

我在 MongoDB 中有以下场景:

每条记录都有自己的 _id 和 parentId。如果 parentId== "" 那么它是一个真正的父记录。如果 parentId 具有值,则该记录实际上是指向父记录的子记录。下面显示了一个父级及其链接的子级。

{"_id": ObjectId('586c9d275d2f62e1634978db'), parentId="", count=1, <other fields>}
{"_id": ObjectId('586c9d275d2f62e163497811'), parentId=ObjectId('586c9d275d2f62e1634978db'), count=3, <other fields>}

我想要一个查询,通过该查询可以找到按计数字段排序的所有父记录,其中所有父记录和子记录都分组在一起。例如,通过图表最容易解释:

ID6 具有与父 ID5 关联的最高计数值。下一个最高计数是 ID2,它与父 ID1 关联,最后 ID4 是父 ID,也应该返回,因此结果应该是:

ID5、ID1、ID4

HoefMeistert 帮助我提出了以下查询:

MongoDB sorting on children

db.collection.aggregate(
  [
    {
      $project: {
      group_id : { $cond : { if: { $ne: [ "$parentId", "" ] }, then: "$parentId", else: "$_id" }},
      count :1,
      field1:1,
      field2:1
      }
    },
    {
      $group: {
      _id : "$group_id",
      highest : { $max: "$count" }
      },
      "field1":{"$first":"$field1"},
      "field2":{"$first":"$field2"},
    },
    {
      $sort: {
      highest : -1
      }
    }
  ]
);

这个查询的问题是它没有返回与父级关联的 field1 和 field2,即图中的 ID1 和 ID5。有没有办法在小组赛阶段投射与父母相关的正确字段?否则,如果小组赛返回类似:

{'_id': ObjectId('586c9d275d2f62e1634978db'), 'highest': 2}
{'_id': ObjectId('586c9d0d5d2f62e1634978d5'), 'highest': 1}
{'_id': ObjectId('586c9d365d2f62e1634978e3'), 'highest': 0}

如何在组后重新匹配以拉回上述所有 Id 的全部记录? IE。 586c9d275d2f62e1634978db, 586c9d0d5d2f62e1634978d5, 586c9d365d2f62e1634978e3 ??

【问题讨论】:

  • 不介意使用 mongodb 3.4 的功能

标签: mongodb


【解决方案1】:

您的查询有错误,field1field2 需要在 $group 字典内:

db.collection.aggregate([
    {
      $project: {
          group_id: { $cond: { if: { $ne: [ "$parentId", "" ] }, then: "$parentId", else: "$_id" }},
          count: 1,
          field1: 1,
          field2: 1
      }
    },
    {
      $group: {
        _id: "$group_id",
        highest: { $max: "$count"},
        field1: { "$first": "$field1"},
        field2: { "$first":" $field2"},
      },
    },
    {
      $sort: {
        highest : -1
      }
    }
]);

结果基于您的图表:

{ "_id" : "5", "highest" : 5, "field1" : ..., "field2" : ... }
{ "_id" : "1", "highest" : 3, "field1" : ..., "field2" : ... }
{ "_id" : "4", "highest" : 1, "field1" : ..., "field2" : ... }

编辑:

db.collection.aggregate([
    {
        $项目:{
            group_id: { $cond: { if: { $ne: [ "$parentId", "" ] }, then: "$parentId", else: "$_id" }},
            计数:1,
            field1: { $cond: { if: { $ne: [ "$parentId", "" ] }, then: null, else: "$field1" }},
            field2: { $cond: { if: { $ne: [ "$parentId", "" ] }, then: null, else: "$field2" }},
        }
    },
    {
        $组:{
            _id: "$group_id",
            最高:{ $max: "$count"},
            字段1:{“$max”:“$field1”},
            字段2:{ "$max":"$field2"},
        },
    },
    {
        $排序:{
            最高:-1
        }
    }
]);

通过此编辑,在小组赛阶段,只有父母拥有field1field2 的值,其他文档将拥有null 的值。比我们可以做一个$max 来获得唯一的值,父值。

结果与上面相同,field1field2 将具有来自父文档的值

【讨论】:

  • 嗨,Sergiu,感谢您指出这一点,这是一个错字,原始代码中包含它们。然而,这不是问题。投影的字段可能仍不属于父项
  • 不错,看来它会起作用,谢谢 Sergiu。在我接受这个作为答案之前,虽然我只是在研究我认为可能提供更优雅的解决方案的 graphLookup 功能。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-15
  • 1970-01-01
  • 1970-01-01
  • 2018-12-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多