嵌套级别的 MongoDB 聚合

MongoDB Aggregation on nested levels

提问人:skumy 提问时间:11/15/2023 最后编辑:Yong Shunskumy 更新时间:11/16/2023 访问量:83

问:

我使用MongoDB 4.4。

我正在尝试进行一个 Mongo 聚合查询,该查询将返回一个带有嵌套数组的文档。要指定上下文,请执行以下操作: 我有报价,其中包含模块,其中包含项目,这些项目本身包含注释。我为每个实体都有一个集合:

offers: {
    _id: '64a6c6ed3f24ff001b74cf9d',
    name: 'offer name',
}

modules: {
    _id: '64a6c6ed3f24ff001b74cfab',
    name: 'module name',
    offerId: '64a6c6ed3f24ff001b74cf9d',
}

items: {
    _id: '5e984aea5e6df000399e6b97',
    name: 'module name',
    moduleId: '64a6c6ed3f24ff001b74cfab',
}

notes: {
    _id: '64c78caf0e5791001b15833c',
    name: 'note name',
    itemId: '5e984aea5e6df000399e6b97',
}

在我的查询中,我想通过 检索选件,此查询返回选件及其模块、每个模块的项以及每个项的注释。基本上是这样的对象:_id

offer: {
  _id: "64a6c6ed3f24ff001b74cf9d",
  name: "offer name",
  modules: [
    {
      _id: "64a6c6ed3f24ff001b74cfab",
      name: "module name",
      items: [
        {
          _id: "5e984aea5e6df000399e6b97",
          name: "item name",
          notes: [
            {
              _id: "64c78caf0e5791001b15833c",
              name: "note name"
            },
            {
              // other note
            },
            ...
          ]
        },
        {
          // other item
        },
        ...
      ]
    },
    {
      // other module
    },
    ...
  ]
}

我写了这个查询:

db.getCollection("offers").aggregate([
  {
    $match: {
        _id: ObjectId('64a6c6ed3f24ff001b74cf9d'),
    }
  },
  {
      $lookup: {
          from: 'modules',
          localField: '_id',
          foreignField: 'offerId',
          as: 'modules',
      },
  },
  {
      $unwind: '$modules',
  },
  {
      $lookup: {
          from: 'items',
          localField: 'modules._id',
          foreignField: 'moduleId',
          as: 'items',
      },
  },
  {
      $unwind: '$items',
  },
  {
    $lookup: {
        from: 'notes',
        localField: 'items._id',
        foreignField: 'itemId',
        as: 'notes',
    },
  },
  {
      $group: {
        _id: "$_id",
        name: { $first: "$name" },
        modules: { 
            $push: {
                _id: "$modules._id",
                name: "$modules.name",
                items: {
                    $push: {
                        _id: "$items._id",
                        name: "$items.name",
                        notes: {
                          $push: {
                              _id: "$notes._id",
                              name: "$notes.name",
                          }
                        },
                    }
                },
            }
        }
      }
  },
  {
      $project: {
        _id: 1,
        name: 1,
        modules: 1,
      }
  },
  
]);

但是当我运行它时,我收到此错误:

无法识别的表达式“$push”

嵌套(es)是不可能的吗?在这种情况下,如何达到预期的结果?$push

提前致谢。

mongodb -查询 聚合框架

评论

0赞 Rubén Vega 11/15/2023
您能补充一些您的收藏文档的代表性示例吗?
0赞 skumy 11/15/2023
我已经更正了查询并添加了集合详细信息,谢谢。
1赞 user20042973 11/15/2023
嵌套查找是否有效,而不是展开然后重新组合?
0赞 skumy 11/15/2023
我该怎么做?有什么例子吗?

答:

1赞 Joe 11/16/2023 #1

聚合运算符在嵌套值中无效。要获得所需的结果,请为每个级别使用单独的$group,例如:$push

{$group:{
  _id:{
       _id:"$_id", 
       module:{_id:"$modules._id", name:"$modules.name"},
       item:{_id:"$garantyItems._id", name:"$garantyItems.name"}
  },
  notes:{$push:{ _id:"$notes._id", name:"$notes.name"}}
}},
{$group:{
  _id:{
        _id:"$_id._id",
        module:"$_id.module",
  },
  items:{$push:{_id:"$_id.item._id",name:"$_id:item.name",notes:"$notes"}}
}},
{$group:{
  _id:"$_id._id",
  modules:{$push:{_id:"$_id.module._id",name:"$_id.module.name",items:"$items"}}
}}
1赞 Yong Shun 11/16/2023 #2

根据评论中提到的@user20042973,嵌套阶段应该更容易加入嵌套数组中的多个集合并自定义其投影。$lookup

db.offers.aggregate([
  {
    $match: {
      _id: ObjectId("64a6c6ed3f24ff001b74cf9d")
    }
  },
  {
    $lookup: {
      from: "modules",
      localField: "_id",
      foreignField: "offerId",
      pipeline: [
        {
          $lookup: {
            from: "items",
            localField: "_id",
            foreignField: "moduleId",
            pipeline: [
              {
                $lookup: {
                  from: "notes",
                  localField: "_id",
                  foreignField: "itemId",
                  pipeline: [
                    {
                      $unset: "itemId"
                    }
                  ],
                  as: "notes"
                }
              },
              {
                $unset: "moduleId"
              }
            ],
            as: "items"
          }
        },
        {
          $unset: "offerId"
        }
      ],
      as: "modules"
    }
  }
])

演示 @ Mongo Playground

评论

0赞 skumy 11/16/2023
感谢您的回复,它适用于 Mongo 6,但使用我的 Mongo 版本 (4.4) 我有一个错误:带有“pipeline”的$lookup可能不会指定“localField”或“foreignField”
1赞 Yong Shun 11/16/2023
嗨,@skumy,在这种情况下,您应该将查询修改为这个演示