2015-01-13 13 views
11

Angenommen, ich habe eine Sammlung wie folgt aus:Mongo Abfrage auf mehreren Feldern von Sub-Dokument

{ "arr" : [ { "name" : "a", "num" : 1 }, { "name" : "a", "num" : 2 } ] }, 
{ "arr" : [ { "name" : "b", "num" : 1 }, { "name" : "a", "num" : 2 } ] }, 
{ "arr" : [ { "name" : "b", "num" : 1 }, { "name" : "b", "num" : 2 } ] } 

und ich möchte alle Dokumente finden, die arr ist enthält ein Teildokument mit einem name = „b“ und num = 2.

Wenn ich eine Abfrage wie folgt aus:

db.collection.find({ 
    $and: [ 
     { "arr.name": "b" }, 
     { "arr.num": 2 } 
    ] 
}); 

es werden alle Dokumente in der Sammlung zurück, weil sie jeweils eine su enthalten b-Dokument entweder mit einem name von „b“ oder ein num von 2.

Ich habe dies auch versucht:

db.collection.find({ 
    arr: [ 
     { "name": "b", "num": 2 } 
    ] 
}); 

, die keine Fehler werfen, hat noch nicht wieder keine Ergebnisse .

Wie fragen Sie nach mehreren Unterdokumentfeldern in MongoDB ab?

Antwort

22

Dies ist tatsächlich, was der $elemMatch Operator ist, obwohl es oft missbraucht wird. Es führt im Wesentlichen die Abfragebedingungen für jedes Element innerhalb des Arrays aus. Alle MongoDB Argumente sind ein „und“ Betrieb sofern nicht ausdrücklich anders genannt:

db.collection.find({ "arr": { "$elemMatch": { "name": "b", "num": 2 } } }) 

Sie wahrscheinlich auch hier wollen auch auf „Projekt“, wenn Sie nur die angepassten Feld und nicht dass ganzes Dokument erwartet:

db.collection.find(
    { "arr": { "$elemMatch": { "name": "b", "num": 2 } } }, 
    { "arr.$": 1 } 
) 

schließlich zu erklären, warum Ihr zweiter Versuch nicht funktioniert, diese Abfrage:

db.collection.find({ 
    "arr": [ 
     { "name": "b", "num": 2 } 
    ] 
}) 

etwas nicht passt, weil es keine tatsächlichen tun ist, cument, wobei "arr" ein einzelnes Element enthält, das genau zu Ihren Bedingungen passt.

Ihr erstes Beispiel fehlgeschlagen ..:

db.collection.find({ 
    $and: [ 
     { "arr.name": "b" }, 
     { "arr.num": 2 } 
    ] 
}); 

Da mehrere Array-Elemente geben, die die Bedingungen erfüllen und dies nicht nur in Betracht gezogen, dass beide Bedingungen auf das gleiche Element anzuwenden. Das ist, was $elemMatch hinzufügt, und wenn Sie mehr als eine Bedingung benötigen, dann verwenden Sie es hier.

+1

Sehr nützliche und vollständige Antwort, es tut mir leid, nicht zweimal upvote. Danke Neil! – Moppo