【问题标题】:MongoDB / mongoose order by nested object value where other value is equal toMongoDB / mongoose按嵌套对象值排序,其中其他值等于
【发布时间】:2020-02-14 19:19:33
【问题描述】:

我有这个猫鼬模式:

const PostsSchema = new Schema(
  {
    type: { type: String, default: "house", index: true },
    title: { type: String, required: true },
    descriptiopn: String,
    image: String,
    userId: {
      type: Schema.Types.ObjectId,
      ref: "User",
      required: true,
      index: true
    },
    details: [{ name: String, label: String, value: Schema.Types.Mixed }]
  },
  { collection: "posts", timestamps: true }
);

我正在尝试通过details.value 订购文档,其中details.name="something"

例如,如果其中一个详细信息对象如下所示:

{"name":"size", "label":"Size", "value": 50}

我想按 name="size" 的值排序

有没有办法做到这一点,或者我应该以不同的方式构建架构?

感谢您的帮助:)

【问题讨论】:

  • 到目前为止你尝试了什么?

标签: mongodb mongoose mongoose-schema


【解决方案1】:

你可以使用mongodb聚合框架。

首先我们需要$unwind 详细信息,然后能够首先按details.name 排序:"size" 我们正在添加一个带有$addFields 的sortPriority 字段,然后我们是sorting 通过这个sortPriority 字段和details.value。排序后,我们使用 $group$replaceRoot 聚合将我们的集合塑造成原始结构。

您可以使用以下聚合:

db.collection.aggregate([
  {
    $unwind: "$details"
  },
  {
    $addFields: {
      "details.sortPriority": {
        $eq: [
          "$details.name",
          "size"
        ]
      }
    }
  },
  {
    $sort: {
      "details.sortPriority": -1,
      "details.value": -1
    }
  },
  {
    $project: {
      "details.sortPriority": 0
    }
  },
  {
    "$group": {
      "_id": "$_id",
      "details": {
        "$push": "$details"
      },
      "allFields": {
        "$first": "$$ROOT"
      }
    }
  },
  {
    "$replaceRoot": {
      "newRoot": {
        "$mergeObjects": [
          "$allFields",
          {
            "details": "$details"
          }
        ]
      }
    }
  }
])

Playground

示例输入:

[
  {
    _id: ObjectId("5a934e000102030405000000"),
    type: "house",
    title: "title 1",
    userId: "user 1",
    details: [
      {
        "name": "size",
        "label": "Size",
        "value": 50
      },
      {
        "name": "size",
        "label": "Size",
        "value": 70
      },
      {
        "name": "color",
        "label": "Color",
        "value": 60
      }
    ]
  },
  {
    _id: ObjectId("5a934e000102030405000001"),
    type: "house",
    title: "title 2",
    userId: "user 2",
    details: [
      {
        "name": "size",
        "label": "Size",
        "value": 10
      },
      {
        "name": "color",
        "label": "Color",
        "value": 20
      },
      {
        "name": "size",
        "label": "color",
        "value": 30
      }
    ]
  }
]

输出:

[
  {
    "_id": ObjectId("5a934e000102030405000000"),
    "details": [
      {
        "label": "Size",
        "name": "size",
        "value": 70
      },
      {
        "label": "Size",
        "name": "size",
        "value": 50
      },
      {
        "label": "Color",
        "name": "color",
        "value": 60
      }
    ],
    "title": "title 1",
    "type": "house",
    "userId": "user 1"
  },
  {
    "_id": ObjectId("5a934e000102030405000001"),
    "details": [
      {
        "label": "color",
        "name": "size",
        "value": 30
      },
      {
        "label": "Size",
        "name": "size",
        "value": 10
      },
      {
        "label": "Color",
        "name": "color",
        "value": 20
      }
    ],
    "title": "title 2",
    "type": "house",
    "userId": "user 2"
  }
]

在猫鼬中,您可以使用 ModelName.aggregate([...]) 进行聚合

例如,如果您的模型是 Post:

await Post.aggregate([...]);

【讨论】:

  • 非常感谢您的详细回答:)
猜你喜欢
  • 1970-01-01
  • 2021-06-29
  • 1970-01-01
  • 2021-12-14
  • 2018-08-11
  • 1970-01-01
  • 2016-07-09
  • 1970-01-01
  • 2012-02-06
相关资源
最近更新 更多