MongoDB
 sql >> Datenbank >  >> NoSQL >> MongoDB

Mittelung eines Unterdokumentfelds über Dokumente hinweg in Mongo

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