Добавление элемента в массив документов MongoDB в PyMongo без повторной вставки

Я использую MongoDB в качестве базы данных для веб-приложения Python (Pymongo + Bottle). Пользователи могут загружать файлы и дополнительно "помечать" эти файлы во время загрузки. Теги хранятся в виде списка в документе, в соответствии с ниже:

{
    "_id" : ObjectId("561c199e038e42b10956e3fc"),
    "tags" : [ "tag1", "tag2", "tag3" ],
    "ref" : "4780"
}

Я пытаюсь разрешить пользователям добавлять теги к любому документу. Я придумал что-то вроде этого:--5-->

def update_tags(ref, new_tag)
    # fetch desired document by ref key as dict
    document = dict(coll.find_one({'ref': ref}))
    # append new tag
    document['tags'].append(new_tag)
    # re-insert the document back into mongo
    coll.update(document)

(к вашему сведению; ref ключ всегда уникален. это может быть легко _id как хорошо.) Кажется, что должен быть способ просто обновить значение "теги" напрямую, не оттягивая весь документ и не вставляя его повторно. Я что-то упускаю?

любые мысли очень ценятся :)

3 ответов


вам не нужно использовать для получения документа сначала просто используйте .update метод $push оператора.

def update_tags(ref, new_tag):
    coll.update({'ref': ref}, {'$push': {'tags': new_tag}})

поскольку обновление устарело, вы должны использовать find_one_and_update или update_one метод, если вы используете pymongo 2.9 или новее


просто добавить к ответу @ssytvane и ответить @Guarav: вы можете добавить "upsert = True", если он не существует:

def update_tags(ref, new_tag):
    coll.update({'ref': ref}, {'$push': {'tags': new_tag}}, upsert = True)

или

def update_tags(ref, new_tag):
    coll.update_one({'ref': ref}, {'$push': {'tags': new_tag}}, upsert = True)

вы можете просто сделать

1) Если вы хотите добавить одну запись

def update_tags(ref, new_tag):
    coll.update({'ref': ref}, {'$push': {'tags': new_tag}})

например:

{
    "_id" : ObjectId("561c199e038e42b10956e3fc"),
    "tags" : [ "tag1", "tag2", "tag3" ],
    "ref" : "4780"
}
>> update_tags("4780", "tag4")
{'updatedExisting': True, u'nModified': 1, u'ok': 1, u'n': 1}
>> coll.find_one({"ref":"4780"})
{
    "_id" : ObjectId("561c199e038e42b10956e3fc"),
    "tags" : [ "tag1", "tag2", "tag3" , "tag4" ],
    "ref" : "4780"
}

2) Если вы хотите добавить несколько записей

def update_tags(ref, new_tag):
    coll.update({'ref': ref}, {'$pushAll': {'tags': new_tag}}) #type of new_tag is list

например:

{
    "_id" : ObjectId("561c199e038e42b10956e3fc"),
    "tags" : [ "tag1", "tag2", "tag3" ],
    "ref" : "4780"
}
>> update_tags("4780", ["tag5", "tag6", "tag7"])
{'updatedExisting': True, u'nModified': 1, u'ok': 1, u'n': 1}
>> coll.find_one({"ref":"4780"})
{
    "_id" : ObjectId("561c199e038e42b10956e3fc"),
    "tags" : [ "tag1", "tag2", "tag3" , "tag4" , "tag5", "tag6", "tag7" ],
    "ref" : "4780"
}

Примечание: Если ключ еще не присутствует, то mongo создаст новый ключ.