MongoDB / mon goose порядок по вложенному объекту, где другое значение равно - PullRequest
0 голосов
/ 14 февраля 2020

У меня есть этот понедельник goose Схема:

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"

Есть ли способ сделать это или, возможно, мне следует структурировать схему по-другому?

Спасибо за помощь:)

1 Ответ

1 голос
/ 14 февраля 2020

Вы можете использовать структуру агрегации mongodb.

Сначала нам нужно $ раскрутить подробностей, затем, чтобы иметь возможность сначала отсортировать по details.name: "size" мы добавляем sortPriority поле с $ addFields , тогда мы сортируем по этому полю sortPriority и details.value. После сортировки мы используем агрегаты $ group и $ replace Root, чтобы придать нашим коллекциям исходную структуру.

Вы можете использовать следующий агрегат:

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"
          }
        ]
      }
    }
  }
])

Детская площадка

Пример ввода:

[
  {
    _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"
  }
]

В пн goose Вы можете использовать агрегацию, используя ModelName.aggregate([...])

Например, если ваша модель ise Post:

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