2017-05-09 4 views
0

In einer Sammlung mit der folgenden allgemeinen Struktur:Zugreifen auf externe Parameter und Dokument in mongodb Gruppe Aggregation

{_id: 'id1', clientId: 'cid1', clientName:'Jon', item: 'item1', dateOfPurchase: '...'}, 
{_id: 'id2', clientId: 'cid1', clientName:'Jon', item: 'item2', dateOfPurchase: '...'}, 
{_id: 'id3', clientId: 'cid2', clientName:'Doe', item: 'itemX', dateOfPurchase: '...'} 
... etc 

Das Ziel ist, eine Gruppierung von clientId zu erstellen einigen einfachen Statistiken zu berechnen, z.B. Gesamterscheinungen pro Client-ID.

Eine Möglichkeit, diese unter Verwendung von Node.js MongoDB Treiber-API Collection.group method zu erreichen ist:

db.collection.group(
    'clientId', 
    {}, 
    { count: 0 }, 
    function(obj, prev) { 
     prev.count++; 
    }, 
    true 
} 

Der Ausgang dieses für die Abtastdaten oben würde ähnlich sein:

{clientId: 'cid1', count: 2} 
{clientId: 'cid2', count: 1} 

Frage 1 : Was ist der beste Weg, um einige externe Werte an die reducer Funktion zu übergeben? Ich möchte zum Beispiel verschiedene Zählungen für Einkäufe vor/nach einem bestimmten Datum berechnen und dieses Datum als Parameter übergeben. Ich weiß, dass mit mapReduce ich die scope Option für diesen Zweck verwenden kann. Ich frage mich, ob es eine Möglichkeit gibt, dies mit der group Funktion zu tun. Ich könnte das Iterator-Objekt verwenden, aber es fühlt sich hacky an.

Frage 2: Gibt es eine Möglichkeit, auf das Originaldokument innerhalb der finalize-Funktion zuzugreifen, um einige zusätzliche Daten in die Ergebnisse einzubeziehen? dh Projekt zusätzliche Felder aus den Originaldokumenten wie clientName:

{clientId: 'cid1', count: 2, clientName: 'Jon'} 
{clientId: 'cid2', count: 1, clientName: 'Doe'} 

Klärungen für Frage 2, a) ich das zusätzliche Feld innerhalb der reducer Funktion hinzufügen könnte, aber es fühlt sich an redundanten Code enthalten, die angeblich nicht laufen bei jeder Iteration. b) ich Aggregat Pipelines verwenden könnte so etwas wie dies zu erreichen, aber ich frage mich, ob ich das mit Collection.group

hier tun kann

Antwort

0

Während rund um die Dokumentation Graben fand ich eine Antwort auf Frage 1 die die Code class zu verwenden ist für die Reduzierfunktion. Der Code Konstruktor nimmt ein zweites Argument funktioniert genau wie scope in mapReduce z.B .:

const myFunction = function(obj, prev) { 
    if (prev.count < myLimit) // myLimit is available here because it is defined in the Code initialization below 
     prev.count++; 
} 

Code = require('mongodb').Code; 
db.collection.group(
    'clientId', 
    {}, 
    { count: 0 }, 
    new Code(myFunction, { myLimit: 5 }), 
    true 
} 
Verwandte Themen