Чтобы переместить элемент в массиве MongoDB, надежнее всего прочитать документ, пересобрать массив в нужном порядке в приложении и записать новый массив через $set. В MongoDB есть операторы $pull, $push, $position, но универсальной команды «передвинь элемент с позиции 5 на позицию 2» для любого массива нет. Если порядок важен, лучше контролировать его явно
Допустим, документ задачи выглядит так:
{
_id: ObjectId("665f1c1a7b8c2e0012a4d111"),
title: "План урока",
blocks: ["intro", "example", "practice", "faq"]
}
Нужно переместить practice сразу после intro
Вариант 1: пересобрать массив
В приложении логика выглядит так:
const doc = await db.collection("lessons").findOne({ _id: lessonId });
const item = "practice";
const withoutItem = doc.blocks.filter((block) => block !== item);
withoutItem.splice(1, 0, item);
await db.collection("lessons").updateOne(
{ _id: lessonId },
{ $set: { blocks: withoutItem } }
);
После этого массив станет таким:
["intro", "practice", "example", "faq"]
Этот способ понятен и хорошо работает, если массив не огромный и порядок меняет пользователь: например, перетаскивает пункты списка, блоки урока, фотографии товара или этапы проекта
Вариант 2: удалить и вставить
Если вы точно знаете значение элемента, можно сделать два обновления: сначала убрать элемент, потом вставить его на нужную позицию
db.lessons.updateOne(
{ _id: lessonId },
{ $pull: { blocks: "practice" } }
)
db.lessons.updateOne(
{ _id: lessonId },
{ $push: { blocks: { $each: ["practice"], $position: 1 } } }
)
Такой подход короче, но есть важный нюанс: между двумя операциями документ уже изменен. Если порядок критичен и несколько пользователей могут менять массив одновременно, лучше использовать транзакцию или одну операцию с пересобранным массивом и проверкой версии документа
Как проверить результат
После обновления перечитайте документ:
db.lessons.findOne(
{ _id: lessonId },
{ blocks: 1 }
)
Проверьте три вещи: элемент остался один раз, он стоит на нужной позиции, остальные элементы не потерялись. Для пользовательского интерфейса полезно хранить не только массив строк, а массив объектов:
blocks: [
{ id: "intro", title: "Вступление" },
{ id: "practice", title: "Практика" }
]
Так вы перемещаете элемент по стабильному id, а не по тексту, который может измениться
Частые ошибки
Перемещают по индексу без проверки
Индекс мог измениться после другого обновления. Сначала найдите элемент по id, затем меняйте порядок
Используют $push, но забывают $each
Для $position нужен $each, даже если вставляете один элемент
Получают повтор элемента
Если сначала не удалить старое значение, $push добавит еще один такой же элемент
Хранят слишком большой массив
Если массив постоянно растет, подумайте об отдельной коллекции с полем position. Так сортировка будет проще и безопаснее
Что почитать дальше по MongoDB
Если нужен общий маршрут по теме, откройте рубрику MongoDB. Для соседних задач пригодятся эти разборы:
- MongoDB: как оставить в массиве элемент с максимальным значением
- Как обновить ключ у всех объектов в массиве MongoDB
- Discord bot на Python и MongoDB: как задать проверку
- Failed to start MongoDB database server: что проверить
Как проверить результат на практике
Для MongoDB-материала полезно делать три проверки: сначала выполнить команду на маленьком наборе тестовых документов, затем посмотреть результат через find() или MongoDB Compass, а после этого повторить действие на копии реальной структуры данных. Если запрос меняет документы, сначала запускайте его с фильтром на один документ и только потом расширяйте условие
Еще одна хорошая привычка — записывать исходное состояние и ожидаемый результат. Например: было три документа, после обновления изменился только один; был массив из пяти элементов, после операции остался нужный элемент; индекс появился в getIndexes(). Такая проверка быстро показывает, что вы исправили именно задачу, а не просто получили команду без ошибки



