Как найти индекс максимального значения в массиве с отсутствующим полем в mongodb?

Вот очень простой пример данных ниже:

[
  {
    "data": [
      {
        "uid": "0",
        "value": 0,
        
      },
      {
        "uid": "1",
        "value": 1,
        
      },
      {
        "uid": "2",
        "value": 2,
        
      }
    ]
  }
]

Затем я хочу найти соответствующее uid максимума value. В моем случае результат должен быть "2".

Вот запрос, с которым я играю:

db.collection.aggregate([
  {
    "$project": {
      "_id": 0,
      "value_argmax": {
        "$arrayElemAt": [
          "$data.uid",
          {
            "$indexOfArray": [
              "$data.value",
              {
                "$max": "$data.value"
              }
            ]
          }
        ]
      }
    }
  }
])

Код работает для моего случая. Однако при наличии некоторых отсутствующих полей код запроса может завершиться ошибкой. Например, если у меня есть пример данных, который выглядит следующим образом:

[
  {
    "data": [
      {
        "uid": "0",
        // "value": 0, // missing field
        
      },
      {
        "uid": "1",
        "value": 1,
        
      },
      {
        "uid": "2",
        "value": 2,
        
      }
    ]
  }
]

Результатом моего запроса будет «1» вместо «2» (в моем случае я просто хочу опустить отсутствующее поле).

Итак, что мне делать, чтобы исправить мой запрос? Вот простой тестовый пример: https://mongoplayground.net/p/8qiFRB8EsSE

Заранее спасибо!

Что вы ожидаете, когда максимальное значение существует более одного раза?

Wernfried Domscheit 22.12.2020 09:17

В этом случае просто верните соответствующее uid существующего максимального значения first.

kaixin liu 22.12.2020 19:53
Использование JavaScript и MongoDB
Использование JavaScript и MongoDB
Сегодня я собираюсь вкратце рассказать о прототипах в JavaScript, а также представить и объяснить вам работу с базой данных MongoDB.
0
2
159
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

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

db.collection.aggregate([
   {
      $set: {
         data: {
            $filter: {
               input: "$data",
               cond: { $eq: [{ $max: "$data.value" }, "$$this.value"] }
            }
         }
      }
   },
   { $set: { value_argmax: { $first: "$data.uid" } } },
   { $unset: "data" }
])  

Очень хорошее решение, спасибо! Только один вопрос, какая разница между set и project здесь? Я нахожу, что оба работают нормально.

kaixin liu 22.12.2020 20:11
$project показывает указанные поля и удаляет все остальные поля. $set (или псевдоним $addFields) добавляет или обновляет поля, не касаясь других. Итак, в вашем примере не имеет значения, какой из них вы используете.
Wernfried Domscheit 22.12.2020 20:18

Для людей, которые используют более раннюю версию MongoDB, вы можете использовать arrayElemAt с индексом 0 вместо first. В противном случае это может вызвать ошибку запроса.

kaixin liu 22.12.2020 22:20

Другие вопросы по теме