mongoose 如何在聚合MongoDB中将多个$group合并到$project中?

brtdzjyr  于 2023-06-23  发布在  Go
关注(0)|答案(1)|浏览(151)

我在MongoDB中使用聚合来查询数据,但我对$group有一个问题,我想在最终合并多个$group阶段到一个$project,但看起来它似乎不像我预期的那样工作。在下面的代码中,当我执行它时,我没有得到任何结果,除了_id。如何解决此问题?
以下是我的聚合管道:

const user = userCollection.aggregate([
    {
      $match: {
         _id: ObjectId(id)
      }
    },

    // lookup images list
    {
       $lookup: {...}
    },
    {
        $unwind: {
            path: '$images',
            preserveNullAndEmptyArrays: true,
        },
    },
    { $sort: { 'images.createdAt': -1 } },
    {
        $group: {
            _id: '$_id',            
            images: {
                $push: '$images',
            },
        },
    },

    // lookup blocked list
    {
       $lookup: {...}
    },
    {
        $unwind: {
            path: '$blocked',
            preserveNullAndEmptyArrays: true,
        },
    },
    { $sort: { 'blocked.createdAt': -1 } },
    {
        $group: {
            _id: '$_id',            
            blocked: {
                $push: '$blocked',
            },
        },
    },

    // lookup followers list
    {
       $lookup: {...}
    },
    {
        $unwind: {
            path: '$followers',
            preserveNullAndEmptyArrays: true,
        },
    },
    { $sort: { 'followers.createdAt': -1 } },
    {
        $group: {
            _id: '$_id',            
            followers: {
                $push: '$followers',
            },
        },
    },

    {
       $project: {
          _id: 1,
          name: 1,
          age: 1,
          bio: 1,
          images: 1,
          blocked: 1,
          followers: 1,
       }
    }

]);

console.log(user);
// Results: [{ _id: '...' }, { _id: '...' }, { _id: '...' }, { _id: '...' }]
rfbsl7qr

rfbsl7qr1#

需要记住的一般准则是,以下处理数组的顺序是反模式:

  1. $unwind
    1.处理展开的阵列,例如用$match$sort对其进行过滤
  2. $group使用`_id将数据重新组合在一起:'$_id'
    任何时候,您都应该尝试寻找其他可以内联处理数组的运算符,而不必解构然后重构文档。
    在你的情况下,我会做类似以下的事情:
[
  { $match: { ... } },
  { $lookup: { ... as: 'images' } },
  { $lookup: { ... as: 'blocked' } },
  { $lookup: { ... as: 'followers' } },
  {
     $project: {
      _id: 1,
      name: 1,
      age: 1,
      bio: 1,
      images: {
        $sortArray: { input: "$images", sortBy: { createdAt: -1 } }
      },
      blocked: {
        $sortArray: { input: "$blocked", sortBy: { createdAt: -1 } }
      },
      followers: {
        $sortArray: { input: "$followers", sortBy: { createdAt: -1 } }
      },
     }
  }
]

具体来说,我们在最后的$project阶段使用the $sortArray operator来完成前面提到的阵列处理。
$sortArray的简单演示可以在this playground example中找到。
或者,如果在该操作符可用之前的版本上,或者如果需要额外的逻辑,您可以考虑使用$lookup语法:

[
  ...
  { $lookup: 
    {
      from: 'images',
      localField: 'imageField',
      foreignField: 'imageField',
      pipeline: [
        { $sort: { createdAt: -1 } }
      ]
      as: 'images'
    } 
  },
  ...
]

相关问题