web-dev-qa-db-fra.com

Ajouter un élément au tableau de documents MongoDB dans PyMongo sans réinsertion

J'utilise MongoDB comme base de données principale pour Python (PyMongo + Bottle). Les utilisateurs peuvent télécharger des fichiers et éventuellement "baliser" ces fichiers pendant le téléchargement. Les balises sont stockées sous forme de liste dans le document, par ci-dessous:

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

J'essaie d'autoriser les utilisateurs à ajouter de nouvelles balises à n'importe quel document. J'ai trouvé quelque chose comme ça:

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)

(fyi; ref clé est toujours unique. cela pourrait facilement être _id également.) Il semble qu'il devrait y avoir un moyen de mettre à jour directement la valeur des "balises" sans retirer le document entier et réinsérer. Est-ce que j'ai râté quelque chose?

Toutes les pensées sont grandement appréciées :)

19
deadbits

Vous n'avez pas besoin d'utiliser pour récupérer le document d'abord utilisez simplement le .update avec la méthode $Push opérateur.

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

Étant donné que la mise à jour est obsolète, vous devez utiliser le find_one_and_update ou update_one méthode si vous utilisez pymongo 2.9 ou plus récent

23
styvane

Juste pour ajouter à la réponse @ssytvane, et pour répondre à @Guarav: vous pouvez ajouter "upsert = True" s'il n'existe pas:

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

ou

def update_tags(ref, new_tag):
    coll.update_one({'ref': ref}, {'$Push': {'tags': new_tag}}, upsert = True)
2
Kiluvya.A

Vous pouvez simplement faire

1) Si vous souhaitez ajouter une seule entrée

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

par exemple:

{
    "_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) Si vous souhaitez ajouter plusieurs entrées

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

par exemple:

{
    "_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"
}

Remarque: Si la clé n'est pas déjà présente, alors mongo créera une nouvelle clé.

2
Nikhil Fulzele