如何在流星服务器端进行mongo分组 [英] How to do mongo group on Meteor server side

查看:74
本文介绍了如何在流星服务器端进行mongo分组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

meteor mongo外壳上,我可以使用db.collection.group,但可以从Meteor.methods使用,因为Meteor不支持.

On meteor mongo shell I can use db.collection.group but from Meteor.methods I can'd because Meteor don't support it.

我该如何编写一个类似于以下内容的方法:

How could I write a method which would do something similar to:

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 result is array of objects groups by month and then grouped by dates inside months.

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

P.S. orders, is quite big collection and I really want to do grouping in the database.

在1.0.4中有关rawCollection()的信息之后,我尝试了以下方法:

After information about rawCollection() in 1.0.4 I tried this:

  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

推荐答案

从Meteor v1.0.4开始:

As of Meteor v1.0.4:

通过Mongo.Collection

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

So you can call collection.rawCollection() to get the underlying collection object:

var rawCollection = Orders.rawCollection();

rawCollection具有方法group,该方法与MongoDB Shell中的group方法等效.不过,基础节点API是异步的,因此您需要以某种方式将其转换为同步函数.我们不能直接使用Meteor.wrapAsync,因为group接受的函数参数不是主回调,因此我们将使用包装器解决此问题:

This rawCollection has a method group which is equivalent to the group method in the MongoDB shell. The underlying node API is asynchronous, though, so you'll want to convert it to a synchronous function somehow. We can't use Meteor.wrapAsync directly since group takes function arguments that aren't the primary callback, so we'll work around this with a wrapper:

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

在您的方法内部,您可以像在Mongo Shell中的db.orders.group一样调用ordersGroup.但是,参数是单独传递的,而不是在对象中传递的:

Inside your method, you can call ordersGroup like you would db.orders.group in the Mongo shell. However, the arguments are passed separately, rather than in an object:

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

有关更多信息,请参见本文档(尽管请注意,应该省略callback参数,因为我们的异步包装可以解决此问题).

For more information, see this documentation (although note that the callback parameter should be left out, as our async-wrapping takes care of that).

因此,您必须分别传递它们:

So you'll have to pass them in separately:

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子目录中或if (Meteor.isServer)内部).

Of course, this only works on the server, so make sure your method is in server-only code (preferably in the server subdirectory, or inside an if (Meteor.isServer)).

这篇关于如何在流星服务器端进行mongo分组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆