В mongoDb, как удалить элемент массива по его индексу - PullRequest
89 голосов
/ 03 января 2011
{

        "_id" : ObjectId("4d1cb5de451600000000497a"),           
        "name" : "dannie",  
        "interests" : [  
            "guitar",  
            "programming",           
            "gadgets",  
            "reading"  
        ]   
}

В приведенном выше примере предположим, что указанный выше документ находится в коллекции db.people . Как удалить 3-й элемент массива интересов по его index ?

Edit:

Это мое текущее решение:

var interests = db.people.findOne({"name":"dannie"}).interests;  
interests.splice(2,1)  
db.people.update({"name":"dannie"}, {"$set" : {"interests" : interests}});

Есть ли более прямой путь?

Ответы [ 5 ]

130 голосов
/ 04 января 2011

Нет прямого способа извлечения / удаления по индексу массива. На самом деле это открытый вопрос http://jira.mongodb.org/browse/SERVER-1014, за него можно проголосовать.

В качестве обходного пути используется $ unset, а затем $ pull:

db.lists.update({}, {$unset : {"interests.3" : 1 }}) 
db.lists.update({}, {$pull : {"interests" : null}})

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

  • Считать документ из базы данных
  • Обновление документа и удаление элемента в массиве
  • Заменить документ в базе данных. Чтобы убедиться, что документ не изменился с момента его прочтения, мы можем использовать обновление, если текущий шаблон описан в документации mongo
19 голосов
/ 30 октября 2012

Вы можете использовать модификатор $pull операции update для удаления определенного элемента в массиве. Если вы предоставили запрос, он будет выглядеть так:

db.people.update({"name":"dannie"}, {'$pull': {"interests": "guitar"}})

Также вы можете рассмотреть возможность использования $pullAll для удаления всех вхождений. Подробнее об этом на официальной странице документации - http://www.mongodb.org/display/DOCS/Updating#Updating-%24pull

Это не использует индекс в качестве критерия для удаления элемента, но все же может помочь в случаях, подобных вашему. IMO, использование индексов для адресации элементов внутри массива не очень надежно, так как mongodb не соответствует порядку элементов, насколько я знаю.

3 голосов
/ 09 марта 2017

Вместо того, чтобы использовать unset (как в принятом ответе), я решаю это, устанавливая поле в уникальное значение (т.е. не NULL), а затем немедленно вытягивая это значение. Немного безопаснее с точки зрения асинхронности. Вот код:

    var update = {};
    var key = "ToBePulled_"+ new Date().toString();
    update['feedback.'+index] = key;
    Venues.update(venueId, {$set: update});
    return Venues.update(venueId, {$pull: {feedback: key}});

Надеемся, что Монго решит эту проблему, возможно, за счет расширения модификатора $ position для поддержки $ pull и $ push.

2 голосов
/ 21 октября 2014

Я бы рекомендовал использовать поле GUID (я склонен использовать ObjectID) или поле с автоинкрементом для каждого вложенного документа в массиве.

С этим GUID легко выполнить $ pull и быть уверенным, что будет получен правильный. То же самое относится и к другим операциям с массивами.

0 голосов
/ 29 декабря 2017

Вместо использования $ pull мы можем использовать $ pop для удаления элементов в массиве по его индексу.Но вы должны вычесть 1 из позиции индекса для удаления на основе индекса.

Для Eg, если вы хотите удалить элемент в индексе 0, вы должны использовать -1, для индекса 1 вы должны использовать 0 и так далее...

Запрос на удаление третьего элемента (гаджеты):

db.people.update({"name":"dannie"}, {'$pop': {"interests": 1}})

для справки: https://docs.mongodb.com/manual/reference/operator/update/pop/

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...