Wie werden verschachtelte Objekte abgefragt?

204

Ich habe ein Problem beim Abfragen von mongoDB mit der Notation verschachtelter Objekte:

db.messages.find( { headers : { From: "[email protected]" } } ).count()
0
db.messages.find( { 'headers.From': "[email protected]" }  ).count()
5

Ich kann nicht sehen, was ich falsch mache. Ich erwarte, dass die Notation verschachtelter Objekte das gleiche Ergebnis wie die Abfrage der Punktnotation zurückgibt. Wo irre ich mich

Edmondo1984
quelle

Antworten:

419

db.messages.find( { headers : { From: "[email protected]" } } )

Diese Abfrage nach Dokumenten, bei denen headers gleich ist { From: ... } , dh keine anderen Felder enthält.


db.messages.find( { 'headers.From': "[email protected]" } )

Dies betrifft nur das headers.FromFeld, das nicht von anderen Feldern betroffen ist, die in enthalten sind oder fehlen headers.


Punktnotationsdokumente

shx2
quelle
Gibt es eine Möglichkeit, dies ohne die Anführungszeichen um "headers.From" zu tun?
Trysis
Ich weiß es nicht, wundere mich nur und dachte, es könnte manchmal nützlich sein.
Tryse
3
@trysis - In der Praxis habe ich festgestellt, dass das Deklarieren von Inline-Objekten (wie die Beispiele in mongo [ose] docs und in den meisten Beispielen da draußen) in der realen Welt einfach nicht ausreicht. Ich habe conditions['some.path'] = 'value'mir find(conditions, fields, callback);
angewöhnt
Was ist, wenn ich einen Schlüssel habe, der "domain.com" enthält? Dies funktioniert nicht : domains.domain.com. Gibt es eine Problemumgehung für dieses Szenario (ohne die domain.com in etwas anderes zu ändern, z. B. domain_com)?
Rens Tillmann
1
Wenn Sie meinen eigenen Kommentar beantworten, vermeiden Sie am besten, Punkte vollständig in Ihren Schlüsseln zu verwenden. In meiner Lösung habe ich die Domänen als Schlüssel vollständig verworfen und stattdessen ein Slice / Array erstellt.
Rens Tillmann
20

Die beiden Abfragemechanismen funktionieren auf unterschiedliche Weise, wie in den Dokumenten im Abschnitt Unterdokumente vorgeschlagen :

Wenn das Feld ein eingebettetes Dokument enthält (dh ein Unterdokument ), können Sie entweder das gesamte Unterdokument als Wert eines Felds angeben oder das Unterdokument mithilfe der Punktnotation „erreichen“ , um Werte für einzelne Felder im Unterdokument anzugeben :

Gleichheitsübereinstimmungen innerhalb von Unterdokumenten wählen Dokumente aus, wenn das Unterdokument genau mit dem angegebenen Unterdokument übereinstimmt, einschließlich der Feldreihenfolge.


Im folgenden Beispiel stimmt die Abfrage mit allen Dokumenten überein, bei denen der Wert des Feldproduzenten ein Unterdokument ist, das nur das Feld companymit dem Wert 'ABC123'und das Feld addressmit dem Wert '123 Street'in der genauen Reihenfolge enthält:

db.inventory.find( {
    producer: {
        company: 'ABC123',
        address: '123 Street'
    }
});
Edmondo1984
quelle
8
Ich wurde verrückt. Dies scheint mir ziemlich inkonsistent zu sein, da bei der Abfrage von Objekten die direkten Eigenschaften in beliebiger Reihenfolge abgeglichen werden können.
Capaj
7

Da die Abfrage der MongoDB-Sammlung mit Unterdokumenten sehr verwirrend ist , hielt ich es für sinnvoll, die obigen Antworten anhand von Beispielen zu erläutern:

Zuerst habe ich nur zwei Objekte in die Sammlung eingefügt, nämlich: messageals:

> db.messages.find().pretty()
{
    "_id" : ObjectId("5cce8e417d2e7b3fe9c93c32"),
    "headers" : {
        "From" : "[email protected]"
    }
}
{
    "_id" : ObjectId("5cce8eb97d2e7b3fe9c93c33"),
    "headers" : {
        "From" : "[email protected]",
        "To" : "[email protected]"
    }
}
>

Was ist das Ergebnis der Abfrage: db.messages.find({headers: {From: "[email protected]"} }).count()

Dies sollte einer sein, da diese Abfragen für Dokumente nur headersdem Objekt entsprechen {From: "[email protected]"}, dh keine anderen Felder enthalten, oder wir sollten das gesamte Unterdokument als Wert eines Felds angeben.

Also gemäß der Antwort von @ Edmondo1984

Gleichheitsübereinstimmungen in Unterdokumenten Wählen Sie Dokumente aus, wenn das Unterdokument genau mit dem angegebenen Unterdokument übereinstimmt , einschließlich der Feldreihenfolge .

Was sollte aus den obigen Aussagen das folgende Abfrageergebnis sein?

> db.messages.find({headers: {To: "[email protected]", From: "[email protected]"}  }).count()
0

Und was ist, wenn wir die Reihenfolge Fromund das ToGleiche wie die Unterdokumente der zweiten Dokumente ändern ?

> db.messages.find({headers: {From: "[email protected]", To: "[email protected]"}  }).count()
1

Daher stimmt es genau mit dem angegebenen Unterdokument überein , einschließlich der Feldreihenfolge .

Für die Verwendung des Punktoperators denke ich, dass es für jeden sehr klar ist. Sehen wir uns das Ergebnis der folgenden Abfrage an:

> db.messages.find( { 'headers.From': "[email protected]" }  ).count()
2

Ich hoffe, dass diese Erklärungen mit dem obigen Beispiel jemandem mehr Klarheit bei der Suchabfrage mit Unterdokumenten verschaffen .

krishna Prasad
quelle