Wie werden verschachtelte Objekte abgefragt?


204

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

db.messages.find( { headers : { From: "reservations@marriott.com" } } ).count()
0
db.messages.find( { 'headers.From': "reservations@marriott.com" }  ).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

Antworten:


419

db.messages.find( { headers : { From: "reservations@marriott.com" } } )

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


db.messages.find( { 'headers.From': "reservations@marriott.com" } )

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


Punktnotationsdokumente


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'
    }
});

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" : "reservations@marriott.com"
    }
}
{
    "_id" : ObjectId("5cce8eb97d2e7b3fe9c93c33"),
    "headers" : {
        "From" : "reservations@marriott.com",
        "To" : "kprasad.iitd@gmail.com"
    }
}
>

Was ist das Ergebnis der Abfrage: db.messages.find({headers: {From: "reservations@marriott.com"} }).count()

Dies sollte einer sein, da diese Abfragen für Dokumente nur headersdem Objekt entsprechen {From: "reservations@marriott.com"}, 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: "kprasad.iitd@gmail.com", From: "reservations@marriott.com"}  }).count()
0

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

> db.messages.find({headers: {From: "reservations@marriott.com", To: "kprasad.iitd@gmail.com"}  }).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': "reservations@marriott.com" }  ).count()
2

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

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.