在Mongoose中对嵌套的子文档进行sorting和分组

我有一个架构, Comment ,如下所示。 这是一个“评论”和“回复”的系统,但每个评论和回复都有多个版本。 当用户想要查看评论时,我想只返回statusAPPROVED最新版本。

 const Version = new mongoose.Schema({ user: { type: mongoose.Schema.Types.ObjectId, ref: 'User' }, body: String, created: Date, title: String, status: { type: String, enum: [ 'APPROVED', 'OPEN', 'CLOSED' ] } }) const Reply = new mongoose.Schema({ user: { type: mongoose.Schema.Types.ObjectId, ref: 'User' }, created: Date, versions: [ Version ] }) const Comment = new mongoose.Schema({ user: { type: mongoose.Schema.Types.ObjectId, ref: 'User' }, created: Date, versions: [ Version ], replies: [ Reply ] }) 

我已经得到了家长的Comment以显示我想要的代码如下。 不过,我有麻烦应用到子文件, Reply

 const requestedComment = yield Comment.aggregate([ { $match: { query } }, { $project: { user: 1, replies: 1, versions: { $filter: { input: '$versions', as: 'version', cond: { $eq: [ '$$version.status', 'APPROVED' ] } } }, }}, { "$unwind": "$versions" }, { $sort: { 'versions.created': -1 } }, { $group: { _id: '$_id', body: { $first: '$versions.body' }, title: { $first: '$versions.title' }, replies: { $first: '$replies' } }} ]) .exec() 

任何帮助实现与replies子文档相同的结果将不胜感激。 我想以这样的forms返回每个答复的最新APPROVED版本:

 comment: { body: "The comment's body.", user: ObjectId(...), replies: [ { body: "The reply's body." user: ObjectId(...) } ] } 

基本上你只需要从现有的pipe道上继续相同的过程。 但是这次要$unwind退出“版本”每个“答复”条目和$sort在那里。

所以这些是你的pipe道的“额外”阶段。

 // Unwind replies { "$unwind": "$replies" }, // Unwind inner versions { "$unwind": "$replies.versions" }, // Filter for only approved { "$match": { "replies.versions.status": "APPROVED" } }, // Sort on all "keys" and then the "version" date { "$sort": { "_id": 1, "replies._id": 1, "replies.versions.created": -1 }}, // Group replies to get the latest version of each { "$group": { "_id": { "_id": "$_id", "body": "$body", "title": "$title", "replyId": "$replies._id", "replyUser": "$replies.user", "replyCreated": "$replies.created" }, "version": { "$first": "$replies.version" } }}, // Push replies back into an array in the main document { "$group": { "_id": "$_id._id", "body": { "$first": "$_id.body" }, "title": { "$first": "$_id.title" }, "replies": { "$push": { "_id": "$_id.replyId", "user": "$_id.replyUser" }, "created": "$_id.replyCreated", // <-- Value from Reply "body": "$version.body", // <-- Value from specific Version "title": "$version.title" } } }} 

所有这些都取决于你想要的领域,无论是从Reply还是从Version

无论哪个领域,因为你“解开”了两个数组,所以你$group back”两次。

  • 每次Replysorting后,一次获取$first项目

  • 再次使用$push重构"replies"数组

这就是这一切。

如果你仍然在寻找不使用$unwind方法来“sorting”数组,那么MongoDB就不会这么做。


在您的devisebuild议位

作为一个说明,我看到你要去哪里,这是你想要的使用types的错误模型。

将“修订历史”存储在embedded结构中是没有意义的。 你很less在一般的更新和查询操作中使用它,正如这个例子所示,大多数时候你只是想要“最新”的。

所以只要做到这一点,并存储一个“标志”,表示“修订”,如果真的有必要。 这些数据可以存储在主结构的外部,而且您不必为了得到每个请求的“最新接受的版本”而跳过这些环节。