В следующем примере предположим, что документ находится в коллекции db.people .
Как удалить 3-й элемент массива интересов по его индексу ?
{
"_id" : ObjectId("4d1cb5de451600000000497a"),
"name" : "dannie",
"interests" : [
"guitar",
"programming",
"gadgets",
"reading"
]
}
Это мое текущее решение:
var interests = db.people.findOne({"name":"dannie"}).interests;
interests.splice(2,1)
db.people.update({"name":"dannie"}, {"$set" : {"interests" : interests}});
Есть более прямой путь?
Ответы:
Нет прямого способа извлечения / удаления по индексу массива. Фактически, это открытый вопрос http://jira.mongodb.org/browse/SERVER-1014 , вы можете проголосовать за него.
Обходной путь заключается в использовании $ unset, а затем $ pull:
Обновление: как упоминалось в некоторых комментариях, этот подход не является атомарным и может вызвать некоторые состояния гонки, если другие клиенты читают и / или записывают между двумя операциями. Если нам нужно, чтобы операция была атомарной, мы могли бы:
источник
Вы можете использовать
$pull
модификаторupdate
операции для удаления определенного элемента в массиве. Если вы предоставили запрос, он будет выглядеть так:Кроме того, вы можете рассмотреть возможность использования
$pullAll
для удаления всех вхождений. Подробнее об этом на странице официальной документации - http://www.mongodb.org/display/DOCS/Updating#Updating-%24pullЭто не использует индекс в качестве критерия для удаления элемента, но все же может помочь в случаях, подобных вашему. ИМО, использование индексов для адресации элементов внутри массива не очень надежно, поскольку mongodb не согласован с порядком элементов так быстро, как я знаю.
источник
Вместо того, чтобы использовать unset (как в принятом ответе), я решаю эту проблему, устанавливая для поля уникальное значение (т.е. не NULL), а затем сразу же извлекая это значение. Немного безопаснее с точки зрения асинхронности. Вот код:
Надеюсь, mongo решит эту проблему, возможно, расширив модификатор $ position для поддержки $ pull, а также $ push.
источник
Я бы рекомендовал использовать поле GUID (я предпочитаю использовать ObjectID) или поле с автоинкрементом для каждого субдокумента в массиве.
С этим GUID легко выполнить запрос $ pull и быть уверенным, что будет извлечен правильный идентификатор. То же самое и с другими операциями с массивами.
источник
Начиная
Mongo 4.4
с$function
оператор агрегирования позволяет применять настраиваемую функцию javascript для реализации поведения, не поддерживаемого языком запросов MongoDB.Например, чтобы обновить массив, удалив элемент по заданному индексу:
$function
принимает 3 параметра:body
, которая представляет собой функцию, которую нужно применить, параметр которой является изменяемым массивом. Функция здесь просто заключается в использовании splice для удаления 1 элемента с индексом 2.args
, который содержит поля из записи, которыеbody
функция принимает в качестве параметра. В нашем случае"$interests"
.lang
, который является языком, на которомbody
написана функция. Доступно толькоjs
в настоящее время.источник
в Mongodb 4.2 вы можете сделать это:
P - это индекс элемента, который вы хотите удалить из массива.
Если вы хотите удалить из P до конца:
источник
Для людей, которые ищут ответ, используя мангуст с nodejs. Вот как я это делаю.
Я могу переписать этот ответ, если он не очень хорошо понимает, но я думаю, что это нормально.
Надеюсь, это поможет вам, я потерял много времени, столкнувшись с этой проблемой.
источник
Вместо использования $ pull мы можем использовать $ pop для удаления элементов в массиве по его индексу. Но вы должны вычесть 1 из позиции индекса для удаления на основе индекса.
Например, если вы хотите удалить элемент в индексе 0, вы должны использовать -1, для индекса 1 вы должны использовать 0 и так далее ...
Запрос на удаление 3-го элемента (гаджеты):
db.people.update({"name":"dannie"}, {'$pop': {"interests": 1}})
для справки: https://docs.mongodb.com/manual/reference/operator/update/pop/
источник
$pop
можно удалить только первый или последний элемент из массива. Запрос в этом ответе не удаляет третий элемент.