MongoDB: не удалось получить поле «имя», которое имеет максимальное значение в двух похожих поддокументах - PullRequest
0 голосов
/ 26 апреля 2020

У меня есть коллекция test:

{
    "_id" : ObjectId("5exxxxxx03"),
    "username" : "abc",
    "col1" : [
        {
            "colId" : 1
            "col2" : [
                {
                    "name" : "a",
                    "value" : 10
                },
                {
                    "name" : "b",
                    "value" : 20
                },
                {
                   "name" : "c",
                   "value" : 30
                }
            ],
            "col3" : [
                {
                    "name" : "d",
                    "value" : 15
                },
                {
                    "name" : "e",
                    "value" : 25
                },
                {
                    "name" : "f",
                    "value" : 35
                }
            ]
        }
    ]
}

col1 содержит список поддокументов col2 и col3, которые похожи, но передают разные значения. Эти два поддокумента имеют поля name и value.

Теперь мне нужно найти максимум value из col2 или col3 и соответствующий ему name.

Я попробовал следующий запрос:

db.test.aggregate([
    {$unwind: '$col1'},
    {$unwind: '$col1.col2'},
    {$unwind: '$col1.col3'},
    {$group:
        {_id: '$col1.colId',
        maxCol2: {$max: '$col1.col2.value'},
        maxCol3: {$max: '$col1.col3.value'}}},
    {$project:
        {maxValue: {$max: ['$maxCol2', '$maxCol3']},
        name: {$cond: [
            {$eq: ['$maxValue', '$maxCol2']},
            '$col1.col2.name',
            '$col1.col3.name']}}}]).pretty()

Но это привело к следующему без поля name:

{ "_id" : 1, "maxValue" : 35 }

Итак, просто чтобы проверить Если мое состояние правильное или нет, пробовал следующий запрос ($col1.col2.name и $col1.col3.name заменены на 111 и 222 строки):

db.test.aggregate([
    {$unwind: '$col1'},
    {$unwind: '$col1.col2'},
    {$unwind: '$col1.col3'},
    {$group:
        {_id: '$col1.colId',
        maxCol2: {$max: '$col1.col2.value'},
        maxCol3: {$max: '$col1.col3.value'}}},
    {$project:
        {maxValue: {$max: ['$maxCol2', '$maxCol3']},
        name: {$cond: [
            {$eq: ['$maxValue', '$maxCol2']},
            '111',
            '222']}}}]).pretty()

Что дает мне ожидаемый результат:

{ "_id" : 1, "maxValue" : 35, "name" : "222" }

Может ли кто-нибудь подсказать мне, почему я не получаю правильный ответ и как я должен запросить это, чтобы получить правильный вывод?

Правильное значение должно быть:

{ "_id" : 1, "maxValue" : 35, "name" : "f" }

PS - я новичок.

Ответы [ 2 ]

3 голосов
/ 26 апреля 2020

Вы можете использовать ниже агрегации

db.collection.aggregate([
  { "$project": {
    "col1": {
      "$max": {
        "$reduce": {
          "input": "$col1",
          "initialValue": [],
          "in": {
            "$concatArrays": [
              "$$this.col2",
              "$$value",
              "$$this.col3"
            ]
          }
        }
      }
    }
  }}
])

MongoPlayground

0 голосов
/ 27 апреля 2020

Попробуйте это:

Объяснение

Нам нужно добавить дополнительные поля со значениями col2 и col3. Как только мы вычислим максимальное значение, мы получим имя на основе максимального значения.


db.collection.aggregate([
  {
    $unwind: "$col1"
  },
  {
    $unwind: "$col1.col2"
  },
  {
    $unwind: "$col1.col3"
  },
  {
    $group: {
      _id: "$col1.colId",
      maxCol2: {
        $max: "$col1.col2.value"
      },
      maxCol3: {
        $max: "$col1.col3.value"
      },
      col2: {
        $addToSet: "$col1.col2"
      },
      col3: {
        $addToSet: "$col1.col3"
      }
    }
  },
  {
    $project: {
      maxValue: {
        $filter: {
          input: {
            $cond: [
              {
                $gt: [
                  "$maxCol2",
                  "$maxCol3"
                ]
              },
              "$col2",
              "$col3"
            ]
          },
          cond: {
            $eq: [
              "$$this.value",
              {
                $cond: [
                  {
                    $gt: [
                      "$maxCol2",
                      "$maxCol3"
                    ]
                  },
                  "$maxCol2",
                  "$maxCol3"
                ]
              }
            ]
          }
        }
      }
    }
  },
  {
    $unwind: "$maxValue"
  },
  {
    $project: {
      _id: 1,
      maxValue: "$maxValue.value",
      name: "$maxValue.name"
    }
  }
])

MongoPlayground | Слияние col2 / col3 | За документ

...