Ich habe mehrere Artikel und Beispiele durchgesehen und noch keinen effizienten Weg gefunden, um diese SQL-Abfrage in MongoDB durchzuführen (wo es Millionen von gibt Reihen Unterlagen)
Erster Versuch
(zB aus dieser fast doppelten Frage - Mongo-Äquivalent zu SQLs SELECT DISTINCT? )
db.myCollection.distinct("myIndexedNonUniqueField").length
Offensichtlich habe ich diesen Fehler erhalten, da mein Datensatz riesig ist
Thu Aug 02 12:55:24 uncaught exception: distinct failed: {
"errmsg" : "exception: distinct too big, 16mb cap",
"code" : 10044,
"ok" : 0
}
Zweiter Versuch
Ich beschloss, eine Gruppe zu bilden
db.myCollection.group({key: {myIndexedNonUniqueField: 1},
initial: {count: 0},
reduce: function (obj, prev) { prev.count++;} } );
Aber ich habe stattdessen diese Fehlermeldung erhalten:
exception: group() can't handle more than 20000 unique keys
Dritter Versuch
Ich habe es noch nicht versucht, aber es gibt einige Vorschläge, die dies betreffen mapReduce
z.B
- dieses, wie man sich in Mongodb unterscheidet und gruppiert? (nicht akzeptiert, Antwort Autor / OP hat es nicht getestet)
- diese eine MongoDB-Gruppe nach Funktionalitäten (scheint dem zweiten Versuch ähnlich zu sein)
- dieses http://blog.emmettshear.com/post/2010/02/12/Counting-Uniques-With-MongoDB
- dieses https://groups.google.com/forum/?fromgroups#!topic/mongodb-user/trDn3jJjqtE
- dieses http://cookbook.mongodb.org/patterns/unique_items_map_reduce/
Ebenfalls
Es scheint, dass es eine Pull-Anfrage auf GitHub gibt, die die .distinct
Methode korrigiert, um zu erwähnen, dass nur eine Zählung zurückgegeben werden soll, aber sie ist noch offen: https://github.com/mongodb/mongo/pull/34
Aber an diesem Punkt dachte ich, es lohnt sich, hier zu fragen, was ist das Neueste zu diesem Thema? Sollte ich für unterschiedliche Zählungen zu SQL oder einer anderen NoSQL-Datenbank wechseln? oder gibt es einen effizienten weg?
Aktualisieren:
Dieser Kommentar zu den offiziellen MongoDB-Dokumenten ist nicht ermutigend. Ist das richtig?
http://www.mongodb.org/display/DOCS/Aggregation#comment-430445808
Update2:
Das neue Aggregation Framework scheint den obigen Kommentar zu beantworten ... (MongoDB 2.1 / 2.2 und höher, Entwicklungsvorschau verfügbar, nicht für die Produktion)
Antworten:
1) Der einfachste Weg, dies zu tun, ist über das Aggregationsframework. Dies erfordert zwei "$ group" -Befehle: Der erste gruppiert nach unterschiedlichen Werten, der zweite zählt alle unterschiedlichen Werte
pipeline = [ { $group: { _id: "$myIndexedNonUniqueField"} }, { $group: { _id: 1, count: { $sum: 1 } } } ]; // // Run the aggregation command // R = db.runCommand( { "aggregate": "myCollection" , "pipeline": pipeline } ); printjson(R);
2) Wenn Sie dies mit Map / Reduce tun möchten, können Sie. Dies ist auch ein zweiphasiger Prozess: In der ersten Phase erstellen wir eine neue Sammlung mit einer Liste aller eindeutigen Werte für den Schlüssel. Im zweiten Schritt zählen wir () für die neue Sammlung.
var SOURCE = db.myCollection; var DEST = db.distinct DEST.drop(); map = function() { emit( this.myIndexedNonUniqueField , {count: 1}); } reduce = function(key, values) { var count = 0; values.forEach(function(v) { count += v['count']; // count each distinct value for lagniappe }); return {count: count}; }; // // run map/reduce // res = SOURCE.mapReduce( map, reduce, { out: 'distinct', verbose: true } ); print( "distinct count= " + res.counts.output ); print( "distinct count=", DEST.count() );
Beachten Sie, dass Sie das Ergebnis der Zuordnung / Inline-Reduzierung nicht zurückgeben können, da dies möglicherweise die Beschränkung der Dokumentgröße von 16 MB überschreitet. Sie können die Berechnung in einer Sammlung speichern und dann die Größe der Sammlung zählen () oder die Anzahl der Ergebnisse aus dem Rückgabewert von mapReduce () abrufen.
quelle
$group
Anweisung verloren gegangen sind, bevor sie an Mongos zurückgegeben werden?db.myCollection.aggregate( {$group : {_id : "$myIndexedNonUniqueField"} }, {$group: {_id:1, count: {$sum : 1 }}});
direkt zum Ergebnis:
db.myCollection.aggregate( {$group : {_id : "$myIndexedNonUniqueField"} }, {$group: {_id:1, count: {$sum : 1 }}}) .result[0].count;
quelle
Die folgende Lösung hat bei mir funktioniert
quelle