Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/mongodb/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
具有关系的MongoDB分组聚合查询_Mongodb_Aggregation Framework_Grouping - Fatal编程技术网

具有关系的MongoDB分组聚合查询

具有关系的MongoDB分组聚合查询,mongodb,aggregation-framework,grouping,Mongodb,Aggregation Framework,Grouping,假设我在协会收藏中有以下文档: { "id" : 1, "parentId" : 1, "position" : { "x" : 1, "y" : 1 }, "tag" : "Beta" }, { "id" : 2, "parentId" : 2, "position" : { "x" : 2, "y" : 2 }, "tag" : "Alpha" },

假设我在协会收藏中有以下文档:

{
    "id" : 1,
    "parentId" : 1,
    "position" : {
        "x" : 1,
        "y" : 1
    },
    "tag" : "Beta"
},
{
    "id" : 2,
    "parentId" : 2,
    "position" : {
        "x" : 2,
        "y" : 2
    },
    "tag" : "Alpha"
},
{
    "id" : 3,
    "parentId" : 1,
    "position" : {
        "x" : 3,
        "y" : 3
    },
    "tag" : "Delta"
},
{
    "id" : 4,
    "parentId" : 1,
    "position" : {
        "x" : 4,
        "y" : 4
    },
    "tag" : "Gamma"
},
{
    "id" : 5,
    "parentId" : 2,
    "position" : {
        "x" : 5,
        "y" : 6
    },
    "tag" : "Epsilon"
}
我想创建一个聚合查询以生成以下结果:

{
    "_id" : 2,
    "position" : {
        "x" : 2,
        "y" : 2
    },
    "tag" : "Alpha",
    "children" : [
        {
            "position" : {
                "x" : 5,
                "y" : 6
            },
            "tag" : "Epsilon"
        }
    ]
},
{
    "_id" : 1,
    "position" : {
        "x" : 1,
        "y" : 1
    },
    "tag" : "Beta"
    "children" : [
        {
            "position" : {
                "x" : 3,
                "y" : 3
            },
            "tag" : "Delta"
        },
        {
            "position" : {
                "x" : 4,
                "y" : 4
            },
            "tag" : "Gamma"
        }
    ]
}
但是,我只能创建以下分组查询,将“所有相关”文档放入子数组中:

db.association.aggregate([{
   $group  : {
       _id : "$parentId",
       children : {
           $push :  {
                   position : "$position",
                   tag :"$tag"
               }
       }
   }
}])

我不知道如何筛选出特定于“父”点的“位置”和“标记”,并将它们放在顶层。

通过确保文档已排序(父-子1-子2…-子n),我们可以将
分组文档
与第一个子文档(即
)合并。在最后一步中,我们需要从
子数组中删除
父数组

试试这个:

db.association.aggregate([
  {
    $sort: {
      parentId: 1,
      id: 1
    }
  },
  {
    $group: {
      _id: "$parentId",
      children: {
        $push: {
          position: "$position",
          tag: "$tag"
        }
      }
    }
  },
  {
    $replaceRoot: {
      newRoot: {
        $mergeObjects: [
          "$$ROOT",
          {
            $arrayElemAt: [
              "$children",
              0
            ]
          }
        ]
      }
    }
  },
  {
    $addFields: {
      children: {
        $slice: [
          "$children",
          1,
          {
            $size: "$children"
          }
        ]
      }
    }
  }
])

通过确保文档已排序(父-子1-子2…-子n),我们可以将
分组文档
与第一个子文档(即
)合并。在最后一步中,我们需要从
子数组中删除
父数组

试试这个:

db.association.aggregate([
  {
    $sort: {
      parentId: 1,
      id: 1
    }
  },
  {
    $group: {
      _id: "$parentId",
      children: {
        $push: {
          position: "$position",
          tag: "$tag"
        }
      }
    }
  },
  {
    $replaceRoot: {
      newRoot: {
        $mergeObjects: [
          "$$ROOT",
          {
            $arrayElemAt: [
              "$children",
              0
            ]
          }
        ]
      }
    }
  },
  {
    $addFields: {
      children: {
        $slice: [
          "$children",
          1,
          {
            $size: "$children"
          }
        ]
      }
    }
  }
])

虽然瓦利乔恩的答案是有效的,但需要先对其进行排序。 这里有一个不需要排序的解决方案,但是使用stage(它非常适合实现您所需的功能)

  • 第一阶段是做好这项工作
  • 第二个用于过滤没有任何子级的文档
  • 第三个仅用于从子数组中删除父数组。但是,如果您可以删除父级中的自引用,则不再需要最后一个阶段

虽然瓦利乔恩的答案是有效的,但需要先对其进行排序。 这里有一个不需要排序的解决方案,但是使用stage(它非常适合实现您所需的功能)

  • 第一阶段是做好这项工作
  • 第二个用于过滤没有任何子级的文档
  • 第三个仅用于从子数组中删除父数组。但是,如果您可以删除父级中的自引用,则不再需要最后一个阶段

嘿,$graphLookup是一个选项-在这种情况下,任务比$group做得更好@Lukasz@matthpen我也想过
$graphLookup
,但我一直认为
*查找
到目前为止性能很差。我做了一些小的基准测试:插入170万条记录并运行:
$group
$graphLookup
$lookup
(有3种可能的解决方案)。Robo3t执行聚合并返回前50条记录。因此,我由不同的操作员分别执行了每个解决方案,下面是执行时间:
$group
:18.5秒,
$graphLookup
:5.4秒和
$lookup
:96.8秒浪费时间。实际上,
$graphLookup
是最好的解决方案,upvotedHey,$graphLookup是一个选项-在这种情况下,任务比$group做得更好@Lukasz@matthpen我也想过
$graphLookup
,但我一直认为
*查找
到目前为止性能很差。我做了一些小的基准测试:插入170万条记录并运行:
$group
$graphLookup
$lookup
(有3种可能的解决方案)。Robo3t执行聚合并返回前50条记录。因此,我由不同的操作员分别执行了每个解决方案,下面是执行时间:
$group
:18.5秒,
$graphLookup
:5.4秒和
$lookup
:96.8秒浪费时间。确实,
$graphLookup
是最好的解决方案,upvotedHey,我喜欢你的解决方案,但我不能假设我的数据会被订购,但我为你提出的解决方案给出+1,谢谢@Lukasz您可以按
parentId
+
id
字段排序(确保这些字段有索引)嘿,我喜欢您的解决方案,但我不能假设我的数据会被排序,但我为您建议的解决方案提供+1,谢谢@Lukasz您可以按
parentId
+
id
字段排序(确保这些字段有索引)