В MongoDB, как удалить элемент массива по его индексу

{

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

в приведенном выше примере Предположим, что приведенный выше документ находится в db.люди!--4--> коллекция. Как удалить 3-й элемент интересы массив-это индекс?

Edit:

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

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

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

5 ответов


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

обходной путь использует $unset, а затем $pull:

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

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

  • читать документ из базы данных
  • обновите документ и удалите элемент в массиве
  • заменить документ в базе данных. Чтобы убедиться, что документ не изменился с момента его чтения, мы можем использовать обновление, если текущий шаблон описан в документах монго

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

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

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

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


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

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


вместо того, чтобы использовать 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.


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

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

запрос на удаление 3-го элемента (гаджетов):

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

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