如何在Meteor服务器端做mongo组

时间:2015-03-27 07:08:44

标签: mongodb meteor

meteor mongo shell上我可以使用db.collection.group,但是我可以使用Meteor.methods,因为Meteor不支持它。

我怎么能写一个类似于:

的方法
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")}}]}
})

期望结果是按月分组的对象组,然后按月内的日期分组。

P.S。 orders,是一个非常大的集合,我真的想在数据库中进行分组。


在1.0.4中关于rawCollection()的信息后,我尝试了这个:

  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);

我得到了:

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

1 个答案:

答案 0 :(得分:5)

从Meteor v1.0.4开始:

  

通过rawCollection

上的新rawDatabaseMongo.Collection方法,直接访问npm Mongo驱动程序中的集合和数据库对象

因此,您可以调用collection.rawCollection()来获取基础集合对象:

var rawCollection = Orders.rawCollection();

rawCollection的方法group等同于MongoDB shell中的group方法。但是,底层节点API是异步的,因此您希望以某种方式将其转换为同步函数。我们无法直接使用Meteor.wrapAsync,因为group采用的函数参数不是主回调,因此我们将使用包装器解决此问题:

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

在您的方法中,您可以像在Mongo shell中ordersGroup一样调用db.orders.group。但是,参数是分开传递的,而不是在对象中传递:

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

有关详细信息,请参阅this documentation(尽管请注意,{I}}参数应该省略,因为我们的异步包装可以解决这个问题。

所以你必须单独传递它们:

callback

当然,这仅适用于服务器,因此请确保您的方法仅在服务器代码中(最好在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); } ); 子目录中,或在server内。)