webentwicklung-frage-antwort-db.com.de

Wie summiert man den Wert eines Schlüssels über alle Dokumente in einer MongoDB-Sammlung?

Ich habe eine Sammlung in MongoDB:

{ "_id" : ObjectId("4d2407265ff08824e3000001"), "subida" : 3.95 }
{ "_id" : ObjectId("4d2551b4ae9fa739640df821"), "subida" : 6.03 }
{ "_id" : ObjectId("4d255b115ff08821c2000001"), "subida" : 5.53 }
{ "_id" : ObjectId("4d25e8d55ff08814f8000001"), "subida" : 1.96 }

Wie kann ich den Wert eines Schlüssels, z. B. "subida", über alle Dokumente summieren? Mit den oben genannten Dokumenten sollte ich Folgendes erhalten:

{ "subida" : 17.47 }
37
JAM

Ich würde persönlich eine Mapreduce für die Sammlung durchführen:

map ist eine einfache Funktion, die das "subida" -Feld ausgibt. Der Schlüssel sollte derselbe sein, wenn Sie eine einzelne Summe benötigen. Das Ergebnis nach dem Verkleinern ergibt das einzelne Objekt {<key>: <sum>}, wobei <key> der von Ihnen im Emit angegebene Wert ist.

map = function() { emit(<key>, this.subida); }

reduzieren ist auch eine einfache Funktion, die sie summiert:

red = function(k, v) {
  var i, sum = 0;
  for (i in v) {
    sum += v[i];
  }
  return sum;
}

Sie können dann mapreduce in Ihrer Sammlung anrufen <mycollection>:

res = db.<mycollection>.mapReduce(map, red);

Dadurch wird eine temporäre neue Sammlung erstellt, die Sie wie jede andere Sammlung bearbeiten können. Der von mapReduce zurückgegebene Wert enthält mehrere Werte in Bezug auf mapReduce, wie z. B. Zeit, Status ... und Temp. Im Feld "Ergebnis" erstellter Sammlungsname . Um die gewünschten Werte zu erhalten, müssen Sie diese Sammlung abfragen:

db[res.result].find()

Welches sollte Ihnen das Objekt {<key>: <sum>} geben.

Wenn Sie MongoDB 1.7.4 oder höher ausführen, können Sie sich etwas Mühe sparen, indem Sie MongoDB bitten, das Ergebnis direkt zurückzugeben, ohne eine Sammlung zu erstellen:

db.<mycollection>.mapReduce(map, red, {out : {inline: 1}});
15
Yochiro

In diesem Fall ist die Aggregation viel einfacher und effizienter als mapReduce:

db.collection.aggregate({
    $group: {
        _id: '',
        subida: { $sum: '$subida' }
    }
 }, {
    $project: {
        _id: 0,
        subida: '$subida'
    }
})
  1. verwenden Sie $ group mit $ sum, um die Summe zu berechnen
  2. verwenden Sie den Projekt-Operator $ project, um den vom $ group-Operator benötigten ID-Schlüssel zu entfernen
111
Ilya Builuk

Option 0: Verwenden Sie die Aggregationspipeline MongoDB
[NB: Diese Option wurde lange nachdem diese Frage gestellt wurde hinzugefügt, ist aber jetzt der richtige Ansatz.]


Option 1: Alle Datensätze abfragen, nur das Subida-Feld von Mongo zurückgeben und durch iterieren über die Mongo-Cursor-Clientseite addieren.

Option 2: Schreiben Sie einen Map-Reduction-Befehl, der nur das Subdia-Feld (derselbe Schlüssel für alle) ausgeben soll, und anschließend einen Reduction-Befehl, der die Summe ergibt.

Option 3: Verwenden Sie db.eval, um Javascript auf dem Server auszuführen: http://www.mongodb.org/display/DOCS/Server-side+Code+Execution

Option 4: Sammeln Sie "subida" -Werte, wenn Sie Werte in Ihre Sammlung einfügen, sodass Sie jederzeit eine aktuelle Summe zur Hand haben. Sie können die Summe in einem anderen Dokument speichern und atomare Aktualisierungsoperationen verwenden, um sie zu aktualisieren: http://www.mongodb.org/display/DOCS/Atomic+Operations

6
Ian Mercer

Sie können die Sammlung als Array verwenden. Fügen Sie einfach die Werte in einer Schleife hinzu.

Edit : Ja, dies ist eine schlechte Praxis bei großen Datensätzen.

0
oscarcardoso

Verwenden Sie diese einfachste Abfrage, um die Summe des Ergebnisses zu erhalten

db.collection.aggregate({
    $group: {
        _id: '',
        subida: { $sum: '$subida' }
    }
 }
)
0
Shakthifuture