Sie müssen das Aggregationsframework verwenden. Die Aggregation sieht am Ende ungefähr so aus:
db.stack.aggregate([
{ $match: { "samples.key" : "test-key" } },
{ $unwind : "$samples" },
{ $match : { "samples.key" : "test-key" } },
{ $project : { "new_key" : "$samples.key", "new_value" : "$samples.value" } },
{ $group : { `_id` : "$new_key", answer : { $avg : "$new_value" } } }
])
Am besten stellt man sich das Aggregations-Framework wie ein Fließband vor. Die Abfrage selbst ist ein Array von JSON-Dokumenten, wobei jedes Unterdokument einen anderen Schritt in der Assemblierung darstellt.
Schritt 1:$match
Der erste Schritt ist ein einfacher Filter, wie eine WHERE-Klausel in SQL. Wir platzieren diesen Schritt an erster Stelle, um alle Dokumente herauszufiltern, die kein Array-Element enthalten, das test-key
enthält . Wenn Sie dies am Anfang der Pipeline platzieren, kann die Aggregation Indizes verwenden.
Schritt 2:$entspannen
Der zweite Schritt, $unwind
, wird verwendet, um jedes der Elemente im Array "samples" zu trennen, damit wir Operationen über alle ausführen können. Wenn Sie die Abfrage nur mit diesem Schritt ausführen, werden Sie sehen, was ich meine. Um es kurz zu machen:
{ name : "bob",
children : [ {"name" : mary}, { "name" : "sue" } ]
}
wird zu zwei Dokumenten:
{ name : "bob", children : [ { "name" : mary } ] }
{ name : "bob", children : [ { "name" : sue } ] }
Schritt 3:$match
Der dritte Schritt, $match
, ist ein exaktes Duplikat des ersten $match
Stufe, hat aber einen anderen Zweck. Da folgt $unwind
, filtert diese Phase frühere Array-Elemente heraus, jetzt Dokumente, die nicht den Filterkriterien entsprechen. In diesem Fall bewahren wir nur Dokumente mit samples.key = "test-key"
auf
Schritt 4:$project (optional)
Der vierte Schritt, $project
, strukturiert das Dokument neu. In diesem Fall habe ich die Elemente aus dem Array gezogen, damit ich sie direkt referenzieren konnte. Verwenden Sie das obige Beispiel..
{ name : "bob", children : [ { "name" : mary } ] }
wird
{ new_name : "bob", new_child_name : mary }
Beachten Sie, dass dieser Schritt vollkommen optional ist; spätere Phasen könnten auch ohne dieses $project
abgeschlossen werden nach ein paar kleinen Änderungen. In den meisten Fällen $project
ist völlig kosmetisch; Aggregationen haben zahlreiche Optimierungen unter der Haube, wie z. B. das manuelle Einschließen oder Ausschließen von Feldern in einem $project
sollte nicht notwendig sein.
Schritt 5:$group
Schließlich $group
Hier passiert die Magie. Die _id
schätzen, was Sie in der SQL-Welt "gruppieren werden". Das zweite Feld besagt, dass der Durchschnitt über dem Wert liegen soll, den ich in $project
definiert habe Schritt. Sie können $sum
einfach ersetzen um eine Summe auszuführen, aber eine Zähloperation wird normalerweise folgendermaßen durchgeführt:my_count : { $sum : 1 }
.
Das Wichtigste, was hier zu beachten ist, ist, dass der Großteil der Arbeit darin besteht, die Daten so zu formatieren, dass die Durchführung der Operation einfach ist.
Schlussbemerkung
Abschließend möchte ich anmerken, dass dies nicht der Fall wäre Arbeiten Sie an den seit samples.value
bereitgestellten Beispieldaten ist als Text definiert, der nicht in arithmetischen Operationen verwendet werden kann. Wenn Sie interessiert sind, wird das Ändern des Feldtyps hier beschrieben:MongoDB How to change the type of a field