2015-10-17 10 views
8

Ich verwende MongoDB als Back-End-Datenbank für Python-Web-Anwendung (PyMongo + Bottle). Benutzer können Dateien hochladen und diese Dateien optional während des Uploads "markieren". Die Tags werden als Liste im Dokument wie folgt gespeichert:Artikel an MongoDB Dokument-Array in PyMongo ohne Wiedereinfügung anhängen

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

Ich versuche, Benutzern zu erlauben, neue Tags an jedes Dokument anzuhängen. Ich kam mit so etwas wie dies oben: (.. FYI, ref Schlüssel immer eindeutig ist dies leicht _id auch sein könnte)

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) 

Es scheint, wie es eine Möglichkeit sein sollte, nur die ‚Tags‘ zu aktualisieren Wert direkt, ohne das gesamte Dokument zurückzuziehen und wieder einzufügen. Fehle ich hier etwas?

sind Irgendwelche Gedanken sehr geschätzt :)

Antwort

12

Sie müssen zuerst nur das Dokument abzurufen nicht verwenden, um die .update Methode mit dem Betreiber $push verwenden.

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

Seit Update ist veraltet Sie die find_one_and_update oder die update_one Methode verwenden sollten, wenn Sie mit pymongo 2.9 oder neuer

+1

Was ist der Unterschied zwischen den beiden? Nur der Rückgabewert (das Dokument gegenüber einem UpdateResult-Objekt)? Wann benutzt du das eine oder das andere? – stackoverflowwww

+4

Was passiert, wenn das Feld "Tags" nicht existiert? –

+0

Wenn das Feld "Tags" nicht existiert, wird es erstellt. @GauravOjha – styvane

0

einfach hinzufügen Antwort auf @ssytvane und beantworten @Guarav: Sie können hinzufügen " Upsert = True“, wenn es nicht existiert:

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

oder

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

Vielen Dank für Ihren Beitrag zu Stack Overflow. Bitte beachten Sie, dass Code-only-Antworten nicht empfohlen werden, da sie nicht erklären, wie sie das Problem lösen. Anstatt sich auf andere Antworten/Kommentare zu beziehen, sollten Sie Ihre Antwort aktualisieren, um zu erklären, was dies tut und wie das Problem gelöst wird, sodass es eine eigenständige Antwort ist und immer noch sinnvoll ist, falls die andere Antwort oder der Kommentar entfernt wird. – FluffyKitten

1

Sie können einfach tun

1) Wenn Sie einzelne Eintrag

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

zB anhängen möchten:

{ 
    "_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) Wenn Sie möchten, fügen Sie mehrere Einträge

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

zB:

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

Hinweis: Wenn der Schlüssel nicht bereits vorhanden ist, erstellt Mongo einen neuen Schlüssel.

Verwandte Themen