MongoDB

MongoDB: как оставить в массиве элемент с максимальным значением

Если в документе MongoDB есть массив объектов и нужно оставить только элемент с максимальным значением, удобный путь — использовать update с aggregation pipeline: отсортировать массив по нужному полю и взять первый элемент. Например, если в массиве scores лежат результаты игроков, можно оставить только объект с максимальным points

Пример документа:

db.players.insertOne({
  name: "Team A",
  scores: [
    { player: "Anna", points: 12 },
    { player: "Boris", points: 27 },
    { player: "Mira", points: 19 }
  ]
})

Нужно получить:

{
  name: "Team A",
  scores: [
    { player: "Boris", points: 27 }
  ]
}

Решение через $sortArray и $slice

db.players.updateMany(
  {},
  [
    {
      $set: {
        scores: {
          $slice: [
            {
              $sortArray: {
                input: "$scores",
                sortBy: { points: -1 }
              }
            },
            1
          ]
        }
      }
    }
  ]
)

Что здесь происходит:

  • $sortArray сортирует массив scores по points по убыванию;
  • $slice берет первый элемент отсортированного массива;
  • $set записывает результат обратно в поле scores.

Проверка

db.players.findOne({ name: "Team A" })

В массиве scores должен остаться один объект с максимальным points

Если нужно не менять документ, а только вывести максимум

Иногда лучше не обновлять базу, а просто получить лучший элемент в результате запроса:

db.players.aggregate([
  {
    $project: {
      name: 1,
      bestScore: {
        $slice: [
          {
            $sortArray: {
              input: "$scores",
              sortBy: { points: -1 }
            }
          },
          1
        ]
      }
    }
  }
])

Так исходный массив в документе останется прежним

Что делать при одинаковом максимальном значении

Если несколько элементов имеют одинаковый максимум, $slice: 1 оставит только первый после сортировки. Если нужно оставить все элементы с максимальным значением, лучше сначала посчитать максимум, а потом отфильтровать массив. Это уже отдельный сценарий

Для большинства задач вроде «оставить лучший результат» достаточно одного элемента

Частые ошибки

Сортируют по строке вместо числа

Если points хранится как строка, сортировка будет работать не так, как вы ожидаете. Храните числа числами:

points: 27

а не так:

points: "27"

Перезаписывают весь документ

Используйте $set, чтобы изменить только поле scores, а не заменить документ целиком

Меняют данные, хотя нужен только отчет

Если вам нужно просто показать максимум в интерфейсе, используйте aggregate() с $project. Обновление документа нужно только тогда, когда вы действительно хотите удалить остальные элементы массива

Не проверяют пустой массив

Если у части документов scores пустой, результат тоже будет пустым массивом. Это нормально, но лучше заранее понимать, есть ли такие документы

Что почитать дальше по MongoDB

Если нужен общий маршрут по теме, откройте рубрику MongoDB. Для соседних задач пригодятся эти разборы:

Как проверить результат на практике

Для MongoDB-материала полезно делать три проверки: сначала выполнить команду на маленьком наборе тестовых документов, затем посмотреть результат через find() или MongoDB Compass, а после этого повторить действие на копии реальной структуры данных. Если запрос меняет документы, сначала запускайте его с фильтром на один документ и только потом расширяйте условие

Еще одна хорошая привычка — записывать исходное состояние и ожидаемый результат. Например: было три документа, после обновления изменился только один; был массив из пяти элементов, после операции остался нужный элемент; индекс появился в getIndexes(). Такая проверка быстро показывает, что вы исправили именно задачу, а не просто получили команду без ошибки

Подписаться
Уведомить о
guest
0 комментариев
Старые
Новые Популярные

Настройки cookie

0
Оставьте комментарий! Напишите, что думаете по поводу статьи.x