在Mongoose中对嵌套子文档进行排序和分组

诺亚

我有一个架构,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子文档相同的结果的任何帮助我想以这样的形式返回APPROVED每个回复的最新版本:

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

基本上,您只需要在现有管道上继续相同的过程。但这一次是$unwind每个“答复”条目中的“版本”及其$sort在那里。

因此,这些是管道的“附加”阶段。

// 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“两次”退回。

  • 一次$first后按Reply

  • 再一次使用以下命令重建"replies"数组$push

这就是全部。

如果您仍在寻找无需使用即可“就地”对数组进行“排序”的方法$unwind,那么MongoDB尚无法做到这一点。


关于设计的一点建议

作为注释,我看到了要进行的操作,这是您想要的使用类型错误的模型。

在嵌入式结构中存储“修订历史记录”几乎没有意义。您很少会在一般的更新和查询操作中使用它,正如这表明的那样,大多数时候您只需要“最新的”。

因此,只需这样做,并在确实需要的时候存储一个“标志”,指示“修订”。然后可以将该数据存储在主结构的外部,并且您不必为了获得每个请求的“最新接受版本”而跳过这些箍。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

lodash属性在数组和嵌套子数组中搜索

在Python中对嵌套列表进行排序和分组

在Firestore中删除包含所有子集合和嵌套子集合的文档

使用C#中的LINQ对XML文档中的元素进行分组和排序

按嵌套文档之一中的值对文档进行排序

在管道中对Powershell对象进行分组和排序

对Python中的dict进行分组和排序

在Kotlin中对单个列表进行分组和排序的更好方法

按数组长度在Mongoose中对文档进行排序

使用嵌套子句对查询结果进行排序

按嵌套字段对文档进行排序

根据内部列表中的字段对Java中的两个嵌套列表进行排序和分组

根据ElasticSearch中的嵌套子计数对文档进行排序

在mongoDB中添加嵌套子文档的最佳方法

对查询结果基于Mongoose / Mongodb数组中嵌套子文档的desc值进行排序

对嵌套文档中的记录进行分组

嵌套子文档中存在检查键

如何根据日期对wordpress中的帖子进行分组和排序?

使用 arrayFilters 更新 MongoDB 中的嵌套子文档

在java中对数组列表进行分组和排序

如何在 mongoose/mongodb 中对子文档数组进行排序?

更新猫鼬中的嵌套子文档

如何对 spark.rdd 中的列进行分组和排序

如何在 mongodb / mongoose 中对嵌套字段进行排序

mongodb展开和排序嵌套在文档数组中的数组

对包含列表的文档的列表中的元素进行排序和过滤

Mongoose 使用聚合按数组中的日期对文档进行分组

如何查询和排序 Mongoose 子文档

对列表中的前 3 个值进行分组和排序