Agregue el elemento a la matriz de documentos MongoDB en PyMongo sin reinserción

Estoy usando MongoDB como la base de datos de back-end para la aplicación web de Python (PyMongo + Bottle). Los usuarios pueden cargar archivos y, opcionalmente, “etiquetar” estos archivos durante la carga. Las tags se almacenan como una lista dentro del documento, como se muestra a continuación:

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

Estoy tratando de permitir que los usuarios agreguen nuevas tags a cualquier documento. Se me ocurrió algo como esto:

 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) 

(La clave de ref es siempre única. Esto también podría ser fácilmente _id ). Parece que debería haber una manera de actualizar el valor de las “tags” directamente sin retirar todo el documento y volver a insertarlo. ¿Me estoy perdiendo de algo?

Cualquier idea es grandemente apreciada 🙂

No necesita usar para recuperar el documento; solo use el método .update con el operador $push .

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

Ya que la actualización está en desuso, debe usar el find_one_and_update o update_one si está usando pymongo 2.9 o más reciente

Simplemente puedes hacer

1) Si desea añadir una sola entrada.

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

p.ej:

 { "_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 desea añadir varias entradas.

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

p.ej:

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

Nota: Si la clave aún no está presente, mongo creará una nueva clave.

Solo para agregar a @ssytvane answer, y para responder a @Guarav: puedes agregar “upsert = True” si no existe:

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

o

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