流星的平均聚合查询

Ste*_*oss 15 mongodb meteor aggregation-framework

好吧,仍然在我的玩具应用程序中,我想找出一组车主的里程表的平均里程数.这在客户端非常简单,但不能扩展.对?但是在服务器上,我并没有完全看到如何实现它.

问题:

  1. 你如何在服务器上实现某些东西然后在客户端上使用它?
  2. 如何使用mongo的$ avg聚合函数来利用其优化的聚合函数?
  3. 或者替代(2)如何在服务器上进行map/reduce并使其可供客户端使用?

@HubertOG的建议是使用Meteor.call,这是有意义的,我这样做:

# Client side
Template.mileage.average_miles = ->
  answer = null
  Meteor.call "average_mileage", (error, result) ->
    console.log "got average mileage result #{result}"
    answer = result
  console.log "but wait, answer = #{answer}"
  answer

# Server side
Meteor.methods average_mileage: ->
  console.log "server mileage called"
  total = count = 0
  r = Mileage.find({}).forEach (mileage) ->
    total += mileage.mileage
    count += 1
  console.log "server about to return #{total / count}"
  total / count
Run Code Online (Sandbox Code Playgroud)

这似乎工作正常,但它并不是因为尽可能接近Meteor.call是异步调用,并且answer将始终为null返回.处理服务器上的东西似乎是一个常见的用例,我必须忽略一些东西.那会是什么?

谢谢!

And*_*Mao 29

从Meteor 0.6.5开始,集合API还不支持聚合查询,因为没有(直接)方法对它们进行实时更新.但是,您仍然可以自己编写它们,并使它们可用Meteor.publish,但结果将是静态的.在我看来,这样做仍然是可取的,因为您可以合并多个聚合并使用客户端集合API.

Meteor.publish("someAggregation", function (args) {
    var sub = this;
    // This works for Meteor 0.6.5
    var db = MongoInternals.defaultRemoteCollectionDriver().mongo.db;

    // Your arguments to Mongo's aggregation. Make these however you want.
    var pipeline = [
        { $match: doSomethingWith(args) },
        { $group: {
            _id: whatWeAreGroupingWith(args),
            count: { $sum: 1 }
        }}
    ];

    db.collection("server_collection_name").aggregate(        
        pipeline,
        // Need to wrap the callback so it gets called in a Fiber.
        Meteor.bindEnvironment(
            function(err, result) {
                // Add each of the results to the subscription.
                _.each(result, function(e) {
                    // Generate a random disposable id for aggregated documents
                    sub.added("client_collection_name", Random.id(), {
                        key: e._id.somethingOfInterest,                        
                        count: e.count
                    });
                });
                sub.ready();
            },
            function(error) {
                Meteor._debug( "Error doing aggregation: " + error);
            }
        )
    );
});
Run Code Online (Sandbox Code Playgroud)

以上是分组/计数聚合的示例.有些注意事项:

  • 当你这样做时,你自然会进行聚合server_collection_name并将结果推送到另一个名为的集合client_collection_name.
  • 这个订阅不会生效,并且可能会在参数发生变化时更新,因此我们使用一个非常简单的循环来推送所有结果.
  • 聚合的结果没有Mongo ObjectID,因此我们自己生成一些任意的.
  • 聚合的回调需要包含在光纤中.我Meteor.bindEnvironment在这里使用,但也可以使用Future更低级别的控制.

如果您开始组合这些出版物的结果,则需要仔细考虑随机生成的ID如何影响合并框.但是,直接实现这个只是一个标准的数据库查询,除了使用Meteor API客户端更方便.

TL; DR版本:几乎每当你从服务器推出数据时,a publish都比a更好method.

有关不同聚合方式的更多信息,请查看此文章.

  • 没有"谢谢",我不想留下这个答案.这是一个非常棒的答案.我暂时离开了另一个项目,但安德鲁,你显然对此深有体会,我非常感激. (2认同)