MongoDB - 聚合后按ID查找

3
我有一个嵌套数组。进行聚合操作,将子数组作为新根。
Category.aggregate([{$unwind: "$SubCats"}, { $replaceRoot: {newRoot: '$SubCats'}} ])

现在我需要按id查找。

使用以下代码将返回空结果:

Category.aggregate([{$unwind: "$SubCats"}, { $replaceRoot: {newRoot: '$SubCats'}}, {$match: {_id: `${req.params.id}`}} ])

使用$elemMatch在我的Atlas层级中不被支持。并且使用findById()会出现错误:“Category.aggregate(...)。findById不是一个函数”

数组:

[
 {
     _id: '61cae5daf5bfbebd7cf748ee'
     title: 'category 1',
     SubCats: [
         {
             _id: '61cae5daf5bfbebd7cf748ef'
             name: 'subcat 1',
             image: '/assets/images/vr-box-6203301_1920.jpg',
         },
         {
             _id: '61cae5daf5bfbebd7cf748fb'
             name: 'subcat 2',
             image: '/assets/images/galaxy-s20_highlights_kv_00.jpg',
         },
     ]
 },
]

聚合后:

[
 {
   _id: '61cae5daf5bfbebd7cf748ef'
   name: 'subcat 1',
   image: '/assets/images/vr-box-6203301_1920.jpg',
 },
 {
    _id: '61cae5daf5bfbebd7cf748fb'
    name: 'subcat 2',
    image: '/assets/images/galaxy-s20_highlights_kv_00.jpg',
 },
]

_id字段是一个字符串,例如'61cae5daf5bfbebd7cf748ef',还是一个ObjectId,即ObjectId("61cae5daf5bfbebd7cf748ef") - Wernfried Domscheit
你可以使用$filter,而不是$unwind$match - Wernfried Domscheit
@WernfriedDomscheit 它是 ObjectId()。 - abood alwa7sh
@WernfriedDomscheit,您能举个例子吗?关于$filter的。谢谢。 - abood alwa7sh
3个回答

1
我需要从npm安装mongodb,因为我最初没有安装它,因为我连接的是云mongodb数据库。
npm i mongodb

然后导入

import mongodb from 'mongodb'
const {ObjectId} = mongodb

然后这是可行的方法:

Category.aggregate([{$unwind: "$SubCats"}, { $replaceRoot: {newRoot: '$SubCats'}}, {$match: {_id: ObjectId(req.params.id)} } ])

0
为什么不将$match阶段移到管道的开头呢?这样做也会提高管道的性能,因为您不必展开和替换许多无关文档的根节点。
Category.aggregate([ {$match: {_id: `${req.params.id}`}}, {$unwind: "$SubCats"}, { $replaceRoot: {newRoot: '$SubCats'}} ])

如果出于某些原因您不想这样做,那么您必须在整个管道中保留原始的id字段,特别是通过$replaceRoot阶段,像这样:

Category.aggregate([
    {
        $unwind: "$SubCats"
    },
    {
        $replaceRoot: {
            newRoot: {
                $mergeObjects: [
                    '$SubCats',
                    { original_id: "$_id" }
                ]
            }
        }
    },
    {
        $match: {original_id: `${req.params.id}`}
    }
])

谢谢您的回答。但我仍然得到空结果: [] - abood alwa7sh
请确保_id为字符串类型(如果不是),需要将 req.params.id 转换为 ObjectId: {original_id: new ObjectId(req.params.id)} - Tom Slabbaert

0

字段_id是一个ObjectId,因此查询语句必须像这样:

Category.aggregate([
   { $unwind: "$SubCats" }, 
   { $replaceRoot: {newRoot: '$SubCats'} }, 
   { $match: {_id: ObjectId(`${req.params.id}`) } } 
])

但你只需要使用

Category.aggregate([
   { $match: {"SubCats._id": ObjectId(`${req.params.id}`) } } 
])

或使用$filter

Category.aggregate([
   {
      $set: {
         SubCats: {
            $filter: {
               input: "$SubCats",
               cond: { $eq: ["$$this._id", ObjectId(`${req.params.id}`)] }
            }
         }
      }
   }
])

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接