2013-12-15 8 views
6

Ich habe eine einfache, Single-Client-Setup für MongoDB und PyMongo 2.6.3. Das Ziel besteht darin, über jedes Dokument in der Sammlung collection zu iterieren und jedes Dokument im Prozess zu aktualisieren (save). Der Ansatz, den ich bin mit Aussehen grob mag:Wie man Dokumente mit PyMongo iteriert und aktualisiert?

cursor = collection.find({}) 
index = 0 
count = cursor.count() 
while index != count: 
    doc = cursor[index] 
    print 'updating doc ' + doc['name'] 
    # modify doc .. 
    collection.save(doc) 
    index += 1 
cursor.close() 

Das Problem ist, dass save offenbar ist die Reihenfolge der Dokumente in dem Cursor zu ändern. Zum Beispiel, wenn meine Sammlung von drei Dokumenten ist (id s der Übersichtlichkeit halber weggelassen):

{ 
    "name": "one" 
} 
{ 
    "name": "two" 
} 
{ 
    "name": "three" 
} 

die oben genannten Programmausgaben:

> updating doc one 
> updating doc two 
> updating doc two 

jedoch Wenn die Linie collection.save(doc) entfernt wird, wird der Ausgang wird:

> updating doc one 
> updating doc two 
> updating doc three 

Warum passiert das? Was ist der richtige Weg, um Dokumente in einer Sammlung sicher zu iterieren und?

+0

ist dies keine Antwort. Aber probiere '1 + 999 ist 1000' und' '1 + 999 == 1000'. – falsetru

+0

@falsetru thx wurde gerade für die Einfachheit neu erstellt, immer noch Python lernen :). OK jetzt? – paislee

+0

Wie ändern Sie die Dokumente? ist 'doc ['name'] = 'newValue' genug? –

Antwort

10

hilft Antwort gefunden in MongoDB documentation:

Da der Cursor während seiner Lebensdauer nicht isoliert wird, können Schreiboperationen auf ein Dokument intervenieren Ergebnis in einem Cursor, der ein Dokument mehr als einmal zurückgibt, wenn das Dokument geändert wurde. Informationen hierzu finden Sie in den Informationen unter snapshot mode.

Schnappschuss-Modus wird auf dem Cursor aktiviert ist, und macht eine schöne Garantie:

snapshot() durchquert den Index auf das _id Feld und gewährleistet, dass die Abfrage jedes Dokument zurückkehren (in Bezug auf den Wert von das Feld _id) nicht mehr als einmal.

cursor = collection.find(spec={},snapshot=True) 

gemäß PyMongo find()documentation:

Schnappschuss-Modus mit PyMongo zu ermöglichen. Bestätigt, dass dies mein Problem behoben hat.

1

Ich konnte deine Situation nicht neu erstellen, aber vielleicht, ganz oben auf meinem Kopf, weil das Holen der Ergebnisse, wie du es tust, sie sind eins nach dem anderen aus der db, du erschaffst tatsächlich mehr, während du gehst (speichern und dann den nächsten holen).

Sie können versuchen, das Ergebnis in einer Liste geführt (auf diese Weise, Ihr alle Ergebnisse auf einmal zu holen - könnte schwere sein, auf Ihre Anfrage abhängig):

cursor = collection.find({}) 
# index = 0 
results = [res for res in cursor] #count = cursor.count() 
cursor.close() 
for res in results: # while index != count //This will iterate the list without you needed to keep a counter: 
    # doc = cursor[index] // No need for this since 'res' holds the current record in the loop cycle 
    print 'updating doc ' + res['name'] # print 'updating doc ' + doc['name'] 
    # modify doc .. 
    collection.save(res) 
    # index += 1 // Again, no need for counter 

Hoffe, dass es

5

Snapshot macht die Arbeit.

Aber auf Pymongo 2.9 und höher ist die Syntax etwas anders.

cursor = collection.find(modifiers={"$snapshot": True}) 

oder für jede Version,

cursor = collection.find({"$snapshot": True}) 

gemäß der PyMongo documentations

Verwandte Themen