流星平均聚集查询 [英] Average Aggregation Queries in Meteor

查看:175
本文介绍了流星平均聚集查询的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

好吧,还在我的玩具应用程序,我想找出一组车主里程表的平均里程数。这是pretty容易在客户端上,但没有规模。对?但是在服务器上,我并不完全了解如何完成它。

Ok, still in my toy app, I want to find out the average mileage on a group of car owners' odometers. This is pretty easy on the client but doesn't scale. Right? But on the server, I don't exactly see how to accomplish it.

问题:


  1. 如何在服务器上实现的东西,然后用它在客户端上?

  2. 如何使用蒙戈的$平均聚合功能利用其优化的聚集功能?

  3. 或者可以选择在服务器上(2)你怎么做的map / reduce并使其提供给客户?

由@HubertOG的建议是使用Meteor.call,这是有道理的,我这样做:

The suggestion by @HubertOG was to use Meteor.call, which makes sense and I did this:

# 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

这似乎做工精细,但它不会因为尽可能接近我可以告诉 Meteor.call 是一个异步调用和答案将永远是一个返回null。在服务器上处理类似的东西我必须要有只是忽略了一些共同的足够用例看起来。那会是什么?

That would seem to work fine, but it doesn't because as near as I can tell Meteor.call is an asynchronous call and answer will always be a null return. Handling stuff on the server seems like a common enough use case that I must have just overlooked something. What would that be?

谢谢!

推荐答案

由于流星0.6.5中,收集API不支持聚合查询,但因为没有(简单)的方式来做到对他们的实时更新。但是,您仍然可以自己写他们,使他们在一个 Meteor.publish 可用,但结果将是静态的。在我看来,做这种方式仍然是preferable,因为你可以合并多个聚合,并使用客户端收集API。

As of Meteor 0.6.5, the collection API doesn't support aggregation queries yet because there's no (straightforward) way to do live updates on them. However, you can still write them yourself, and make them available in a Meteor.publish, although the result will be static. In my opinion, doing it this way is still preferable because you can merge multiple aggregations and use the client-side collection 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);
            }
        )
    );
});

以上是一个例子分组/计数聚集。值得注意的有些事情:

The above is an example grouping/count aggregation. Some things of note:


  • 当你这样做,你会很自然地对 server_collection_name 做一个汇总和推动的结果,所谓不同的集合 client_collection_name

  • 这个订阅不会是活的,每当参数变化可能会被更新,所以我们用一个非常简单的循环,只是推动所有结果出来。

  • 聚集的结果没有蒙戈的ObjectID,所以我们产生我们自己的。
  • 的一些任意的人
  • 回调到汇聚需要被包裹在一个光纤。我使用 Meteor.bindEnvironment 在这里,但你也可以使用未来更多低级别控制。

  • When you do this, you'll naturally be doing an aggregation on server_collection_name and pushing the results to a different collection called client_collection_name.
  • This subscription isn't going to be live, and will probably be updated whenever the arguments change, so we use a really simple loop that just pushes all the results out.
  • The results of the aggregation don't have Mongo ObjectIDs, so we generate some arbitrary ones of our own.
  • The callback to the aggregation needs to be wrapped in a Fiber. I use Meteor.bindEnvironment here but one can also use a Future for more low-level control.

如果你开始合并同类这些出版物的结果,你需要仔细考虑随机生成的ID如何影响合并框。然而,直接实现的,这只是一个标准的数据库查询,但它与流星的API客户端使用起来更加方便。

If you start combining the results of publications like these, you'll need to carefully consider how the randomly generated ids impact the merge box. However, a straightforward implementation of this is just a standard database query, except it is more convenient to use with Meteor APIs client-side.

TL; DR版本:几乎任何时候你都出从服务器推数据,一个发布是preferable到

TL;DR version: Almost anytime you are pushing data out from the server, a publish is preferable to a method.

有关不同的方式做聚合的信息, 看看这个帖子

For more information about different ways to do aggregation, check out this post.

这篇关于流星平均聚集查询的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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