2015-03-27 11 views
5

Shell auf meteor mongo kann ich db.collection.group verwenden, aber von Meteor.methods konnte ich, weil Meteor es nicht unterstützen.Wie mongo Gruppe auf Meteor Server Seite

Wie könnte ich schreiben eine Methode, die etwas ähnliches tun wäre:

db.orders.group({ 
    keyf: function(doc) {return {year:doc.createdAt.toISOString().substring(0, 4)}}, 
    initial: {months:{}}, 
    reduce: function(order, result) { 
    var month = order.createdAt.getMonth()+1, 
     date = order.createdAt.getDate(); 

    month = result.months[month] || (result.months[month] = {}); 
    date = month[date] || (month[date] = []); 
    date.push(order); 
    }, 
    cond: {$and: [{createdAt: {$gt: new Date("2015-01-01")}, createdAt: {$lt: new Date("2015-12-31")}}]} 
}) 

Expecting Ergebnis ist Array von Objekten Gruppen von Monat und dann von Terminen innerhalb Monate gruppiert.

P.S. orders, ist ziemlich große Sammlung und ich möchte wirklich Gruppierung in der Datenbank tun.


Nach Informationen über rawCollection() in 1.0.4 habe ich versucht, dies:

collection = Orders.rawCollection(); 
    params = { 
    keyf: function(doc) {return {year:doc.createdAt.toISOString().substring(0, 4)}}, 
    initial: {months:{}}, 
    reduce: function(order, result) { 
     var month = order.createdAt.getMonth()+1, 
      date = order.createdAt.getDate(); 

     month = result.months[month] || (result.months[month] = {}); 
     date = month[date] || (month[date] = []); 
     date.push(order); 
    }, 
    cond: {$and: [{createdAt: {$gt: new Date("2015-01-01")}, createdAt: {$lt: new Date("2015-12-31")}}]} 
    }; 
    Meteor.wrapAsync(collection.group, collection)(params); 

Ich erhalte:

W20150327-13:26:24.924(2)? (STDERR) /Users/jaro/.meteor/packages/mongo/.1.1.0.1jqg8g6++os+web.browser+web.cordova/npm/node_modules/mongodb/lib/mongodb/connection/base.js:246 
W20150327-13:26:24.924(2)? (STDERR)   throw message;  
W20150327-13:26:24.924(2)? (STDERR)    ^
W20150327-13:26:24.929(2)? (STDERR) TypeError: undefined is not a function 
W20150327-13:26:24.929(2)? (STDERR)  at /Users/jaro/.meteor/packages/mongo/.1.1.0.1jqg8g6++os+web.browser+web.cordova/npm/node_modules/mongodb/lib/mongodb/collection/aggregation.js:229:22 
W20150327-13:26:24.931(2)? (STDERR)  at /Users/jaro/.meteor/packages/mongo/.1.1.0.1jqg8g6++os+web.browser+web.cordova/npm/node_modules/mongodb/lib/mongodb/db.js:1191:22 
W20150327-13:26:24.931(2)? (STDERR)  at /Users/jaro/.meteor/packages/mongo/.1.1.0.1jqg8g6++os+web.browser+web.cordova/npm/node_modules/mongodb/lib/mongodb/db.js:1903:9 
W20150327-13:26:24.931(2)? (STDERR)  at [object Object].Base._callHandler (/Users/jaro/.meteor/packages/mongo/.1.1.0.1jqg8g6++os+web.browser+web.cordova/npm/node_modules/mongodb/lib/mongodb/connection/base.js:453:41) 
W20150327-13:26:24.932(2)? (STDERR)  at /Users/jaro/.meteor/packages/mongo/.1.1.0.1jqg8g6++os+web.browser+web.cordova/npm/node_modules/mongodb/lib/mongodb/db.js:1758:29 
W20150327-13:26:24.932(2)? (STDERR)  at [object Object].Connection.write (/Users/jaro/.meteor/packages/mongo/.1.1.0.1jqg8g6++os+web.browser+web.cordova/npm/node_modules/mongodb/lib/mongodb/connection/connection.js:272:16) 
W20150327-13:26:24.932(2)? (STDERR)  at __executeQueryCommand (/Users/jaro/.meteor/packages/mongo/.1.1.0.1jqg8g6++os+web.browser+web.cordova/npm/node_modules/mongodb/lib/mongodb/db.js:1752:16) 
W20150327-13:26:24.932(2)? (STDERR)  at Db._executeQueryCommand (/Users/jaro/.meteor/packages/mongo/.1.1.0.1jqg8g6++os+web.browser+web.cordova/npm/node_modules/mongodb/lib/mongodb/db.js:1902:7) 
W20150327-13:26:24.933(2)? (STDERR)  at Db.command (/Users/jaro/.meteor/packages/mongo/.1.1.0.1jqg8g6++os+web.browser+web.cordova/npm/node_modules/mongodb/lib/mongodb/db.js:1183:8) 
W20150327-13:26:24.933(2)? (STDERR)  at Collection.group (/Users/jaro/.meteor/packages/mongo/.1.1.0.1jqg8g6++os+web.browser+web.cordova/npm/node_modules/mongodb/lib/mongodb/collection/aggregation.js:228:13) 
=> Exited with code: 8 

Antwort

5

Ab Meteor v1.0.4:

Direkter Zugriff auf die Sammlungs- und Datenbankobjekte vom npm Mongo-Treiber über neue rawCollection und rawDatabase Methoden auf Mongo.Collection

So können Sie collection.rawCollection() rufen das zugrunde liegende Sammelobjekt zu erhalten:

var rawCollection = Orders.rawCollection(); 

Diese rawCollection hat eine Methode group die das group Verfahren in der MongoDB Schale entspricht . Da die zugrunde liegende Knoten-API jedoch asynchron ist, sollten Sie sie irgendwie in eine synchrone Funktion konvertieren. Wir können Meteor.wrapAsync nicht direkt verwenden, da group Funktion Argumente übernehmen, die nicht der primäre Rückruf sind, so dass wir mit einem Wrapper um diese Arbeit:

function ordersGroup(/* arguments */) { 
    var args = _.toArray(arguments); 
    return Meteor.wrapAsync(function (callback) { 
     rawCollection.group.apply(rawCollection, args.concat([callback])); 
    })(); 
} 

In Ihrer Methode können Sie ordersGroup wie nennen würden Sie db.orders.group in der Mongo-Schale. Allerdings sind die Argumente separat übergeben, anstatt in einem Objekt:

ordersGroup(keys, condition, initial, reduce[, finalize[, command[, options]]]) 

Weitere Informationen finden Sie this documentation (obwohl beachten Sie, dass die callback Parameter weggelassen werden, da unser Asynchron-Wrapping nimmt diese Aufgabe).

So musst du sie separat in weitergeben müssen:

var result = ordersGroup(
    // keys 
    function(doc) { 
     return { year: doc.createdAt.toISOString().substring(0, 4) }; 
    }, 

    // condition 
    {createdAt: {$lt: new Date("2015-12-31"), $gt: new Date("2015-01-01")}}, 

    // initial 
    {months: {}}, 

    // reduce 
    function(order, result) { 
     var month = order.createdAt.getMonth()+1, 
      date = order.createdAt.getDate(); 

     month = result.months[month] || (result.months[month] = {}); 
     date = month[date] || (month[date] = []); 
     date.push(order); 
    } 
); 

Natürlich funktioniert dies nur auf dem Server, so stellen Sie sicher, dass Ihre Methode ist in Server-only-Code (vorzugsweise im server Unterverzeichnis, oder in einem if (Meteor.isServer)).

+0

Ich habe versucht, rawCollection() zu verwenden, funktioniert aber immer noch nicht. Ich bin mir nicht sicher, ob ich es richtig benutze. Irgendwelche Ideen, was ich falsch gemacht habe? (siehe Update in meiner Frage) – Jaro

+0

Sie verwenden 'wrapAsync' falsch, versuchen Sie' Meteor.wrapAsync (Sammlung.gruppe, Sammlung) (params) ' – user3374348

+0

Dank der Korrektur, aber leider bekomme ich immer noch Fehler. (Ich habe gerade meine Frage aktualisiert). – Jaro