2013-08-21 17 views
6

Hinweis: Verwenden Sie die mongodb-Shell, um die Codes auszuführen.Filialdokument in MongoDB-Sammlung aktualisieren/entfernen

Lassen Sie uns sagen, dass ich ein Student Dokument haben, wie unten

{ 
    "_id" : 4, 
"grades" : [ 
    { 
     "grade" : 80, 
     "mean" : 75, 
     "std" : 8 
    }, 
    { 
     "grade" : 85, 
     "mean" : 90, 
     "std" : 5 
    }, 
    { 
     "grade" : 85, 
     "mean" : 90, 
     "std" : 5 
    }, 
    { 
     "grade" : 85, 
     "mean" : 95, 
     "std" : 6 
    }, 
    { 
     "grade" : 90, 
     "mean" : 85, 
     "std" : 5 
    } 
] 
} 

Wir haben 2 Probleme:

Problem 1: können Sie sagen alle Subdokumente mit _id = 4 & & Noten aktualisiert will. Grad = 85 & & grades.std = 5, mit Std = 6 schreiben Sie wie folgt

db.students.update({'$and':[ { _id: 4},{ "grades.grade": 85 }, {"grades.std": 5 } ]}, { $set: { "grades.$.std" : 6 } }); 
Jetzt

, wenn Sie mehrmals (3 mal) oben Anweisung ausführen dann im Idealfall sollten sie aktualisieren 2., 3. Unterlagen

Aber letzte Teildokument wird auch immer aktualisiert beacause es std = 5 Spiel, aber wir habe die Bedingung $ und nicht $ oder gegeben, wie kommt es dann, dass das letzte Dokument aktualisiert wird?

Problem 2: Lassen Sie uns jetzt sagen Sie das Filialdokument selbst Abgleich mit Abfragekriterien entfernen will. Ich habe versucht, folgende Erklärung

db.students.update({_id:4,'grades.grade':85},{'$unset':{'grades.$':1}}) 

weil ungesetzt $ wird bei Unterlagen/Arrays, wie dieses Problem zu lösen null setzen?

Wie in Ihrer mongodb Konsole zu replizieren?

db.students.insert({ "_id" : 4, "grades" : [ { grade: 80, mean: 75, std: 8 }, { grade: 85, mean: 90, std: 5 }, { grade: 85, mean: 90, std: 5 }, { grade: 85, mean: 95, std: 6 }, { grade: 90, mean: 85, std: 5 } ] }); 

Antwort

10

Die '$' Operator aktualisiert nur das erste Spiel so gegeben:

db.students.insert({ "_id" : 4, "grades" : [ 
    { grade: 80, mean: 75, std: 8 }, 
    { grade: 85, mean: 90, std: 5 }, 
    { grade: 85, mean: 90, std: 5 }, 
    { grade: 85, mean: 95, std: 6 }, 
    { grade: 90, mean: 85, std: 5 } ]}); 

So aktualisieren Sie mit $elemMatch wie so ausrichten müssen:

db.students.update({ _id: 4, "grades": {$elemMatch: {"grade": 85, "std": 5 }}}, 
        { $set: { "grades.$.std" : 6 } }); 

Sie haben jedoch zwei Qualitäten, die passen {"grades.grade": 85, "grades.std": 5} und $ aktualisiert nur die erste, so dass Sie Schleife, bis alle aktualisiert werden müssen:

db.students.update({ _id: 4, "grades": {$elemMatch: {"grade": 85, "std": 5 }}}, 
        { $set: { "grades.$.std" : 6 } }) 
while (db.getLastErrorObj()['n'] > 0) { 
    db.students.update({ _id: 4, "grades": {$elemMatch: {"grade": 85, "std": 5 }}}, 
         { $set: { "grades.$.std" : 6 } }) 
} 

Problem 2: Gleiche gilt - man muss $pull Anpasselemente Schleife:

db.students.update({_id:4,'grades': {$elemMatch: {'grade':85}}}, {'$pull': {'grades': {'grade':85}}}) 
+0

Danke für die erste Frage Antwort, habe ich bereits mit @drmirror Antwort versucht. $ pull wird Null im Fall von Filialdokumenten setzen, dann muss ich 2 update Anweisung eine für die Aktualisierung auf Null, eine andere für das Entfernen von null aus Filialdokument ausführen. Ist es möglich, eine Update-Anweisung? –

+0

In 2.4 zieht es die Unterdokumente und nicht als null. – Ross

+0

extrem Sorry, My bad ... es hat funktioniert ... Vielen Dank –

2

Sie müssen $elemMatch verwenden innerhalb eines Arrays zu entsprechen. Die Abfrageregeln in MongoDB geben an, dass bei Bedingungen für Array-Elemente jedes Array-Element, bei dem eine der Bedingungen übereinstimmt, als Übereinstimmung betrachtet wird. Mit $elemMatch müssen alle Bedingungen auf demselben Element übereinstimmen.

+0

Können Sie bitte die Shell-Anweisung für das gleiche aufschreiben? –

+0

ist es möglich, das zweite Problem zu lösen? –

+0

danke .. Ich versuchte mit $ elemMatch und es funktioniert. Aber für das 2. Problem. Ich möchte nicht 2 update Anweisung ausführen, nur um das eine Filialdokument zu entfernen. Gibt es eine Möglichkeit? durch eine Anweisung Ausführung –

0

Punktnotation entspricht Dokumenten, deren Kriterien in einem der Arrayelemente erfüllt werden können.

Wenn Sie nur Dokumente übereinstimmen soll, die bereits beantwortet alle Ihre Kriterien in einem Array-Element (zumindest), dann als drmirror entsprechen, müssen Sie dem Operator elemMatch $ verwenden, siehe auch: $elemMatch Operator

In Ihrem Fall wäre das:

db.students.update({'$and':[ { _id: 4},{ "grades":{"$elemMatch": {"grade": 85, "std": 5 }}} ]}, { $set: { "grades.$.std" : 6 } }); 

Für den zweiten Teil Ihrer Frage, wie Array-Elemente zu entfernen, finden Sie in diesem Post.

In mongoDb, how do you remove an array element by its index

Kurz gesagt, es ist ein zweistufiger Betrieb, dass erste Sätze zu null das Element (wie Sie bereits tun) und dann $ pull (e) es ab.

Verwandte Themen