Zählen Sie, wie viele Dokumente enthalten ein Feld
Habe ich diese drei MongoDB Dokumente:
{
"_id" : ObjectId("571094afc2bcfe430ddd0815"),
"name" : "Barry",
"surname" : "Allen",
"address" : [
{
"street" : "Red",
"number" : NumberInt(66),
"city" : "Central City"
},
{
"street" : "Yellow",
"number" : NumberInt(7),
"city" : "Gotham City"
}
]
}
{
"_id" : ObjectId("57109504c2bcfe430ddd0816"),
"name" : "Oliver",
"surname" : "Queen",
"address" : {
"street" : "Green",
"number" : NumberInt(66),
"city" : "Star City"
}
}
{
"_id" : ObjectId("5710953ac2bcfe430ddd0817"),
"name" : "Tudof",
"surname" : "Unknown",
"address" : "homeless"
}
Den address
Feld ist ein Array
von Objekten in das erste Dokument ein Object
im zweiten und eine String
im Dritten.
Mein Ziel ist es, herauszufinden, wie viele Dokumente meiner Sammlung containinig Bereich address.street
. In diesem Fall die richtige Anzahl ist 1, aber mit meiner Abfrage bekomme ich zwei:
db.coll.find({"address.street":{"$exists":1}}).count()
Ich habe auch versucht, map/reduce. Es funktioniert, aber es ist langsamer, so dass, wenn es möglich wäre, würde ich es vermeiden.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Die Unterscheidung ist hier, dass die
.count()
Bedienung ist tatsächlich "korrigieren" wieder der "Dokument" zählen, wenn das Feld vorhanden ist. So die Allgemeinen überlegungen, die brechen:, Wenn Sie nur wollen, um ausschließlich die Dokumente, die mit dem array-Feld
Dann der effektivste Weg, mit Ausnahme derjenigen Dokumente, in denen die "Straße" war eine Eigenschaft, von der "Adresse" als "array", dann verwenden Sie einfach die Punkt-notation Eigenschaft von der Suche nach der
0
index, die nicht vorhanden in der exlcusion:Als nativ codiert operator test in beiden Fällen
$exists
hat den richtigen job und effizient., Wenn Sie beabsichtigt, Feld Anzahl der Ereignisse
Wenn das, was Sie eigentlich Fragen, ist die "Feld zählen", wo einige "Dokumente" enthalten array-Einträge, bei denen das "Feld" vorhanden sein können mehrmals.
Dafür müssen Sie die aggregation framework oder mapReduce-wie Sie erwähnen. MapReduce verwendet JavaScript-basierte Verarbeitung und wird daher deutlich langsamer sein als die
.count()
Betrieb. Das aggregation framework muss auch berechnen, und "wird" langsamer sein als.count()
, aber nicht so viel wie mapReduce.In MongoDB 3.2 Sie bekommen hier etwas Hilfe durch die erweiterte Fähigkeit der
$Summe
arbeiten auf ein array von Werten als auch eine Gruppierung-Akkumulator. Die anderen Helfer hier ist$isArray
die es erlaubt, eine unterschiedliche Verarbeitung Methode über$anzeigen
, wenn die Daten in der Tat "ein array":Früheren Versionen Scharnier auf ein bisschen mehr bedingte Verarbeitung in der Reihenfolge zu behandeln, das array und nicht-array-Daten anders, und erfordern in der Regel
$entspannen
zu Prozess-array-Einträgen.Entweder der Umsetzung des array über
$anzeigen
mit MongoDB 2.6:Oder die Bereitstellung bedingte Auswahl mit MongoDB 2.2 oder 2.4:
Also die letztere form "sollte" führen Sie ein bisschen besser als mapReduce, aber wahrscheinlich nicht viel.
In allen Fällen die Logik fällt mit
$ifNull
als die "logische" form$exists
für die aggregation framework. Gepaart mit$dir
, ein "wahrhaftig" Ergebnis wird erzielt, wenn die Immobilie tatsächlich exsists, und einfalse
Wert wird zurückgegeben, wenn es nicht ist. Diese bestimmt, ob1
oder0
zurückgegeben wird, die jeweils an der insgesamt-Akkumulation über$Summe
.Idealerweise haben Sie die moderne version, die kann dies in einem einzigen
$group
pipeline-Phase, aber ansonsten braucht man den längeren Weg.Können Sie versuchen, diese:
In der where-Klausel, sind wir ohne wenn Adresse von array-und
Einschließlich Adresse, wenn es den Typ object ist.
$where
. Verwenden Sie einfach"address.0": { "$exists": false }
in den Bedingungen. Da die0
index ist nur vorhanden, wenn das Feld ist in der Tat ein "array".