好的,还是在我的玩具应用程序中,我想找出一组车主里程表上的平均里程.这对客户来说很容易,但无法扩展.正当但在服务器上,我不知道如何实现它.

问题:

  1. 如何在服务器上实现一些东西,然后在客户机上使用它?
  2. 您如何使用mongo的$avg聚合功能来利用其优化的聚合功能?
  3. 或者(2)如何在服务器上进行映射/缩减,并使其可供客户端使用?

@HubertOG的建议是使用Meteor.打电话,这很有道理,我做到了:

# 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是一个异步调用,而answer总是一个空返回.在服务器上处理东西似乎是一个非常常见的用例,我一定忽略了什么.那会是什么?

谢谢

推荐答案

截至Meteor 0.6.5,collection 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);
            }
        )
    );
});

以上是分组/计数聚合的示例.值得注意的是:

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

如果您开始结合这些出版物的结果,您需要仔细考虑随机生成的IDS是如何影响合并框的.然而,这个简单的实现只是一个标准的数据库查询,只是它更方便地与Meteor API客户端一起使用.

TL;DR version:几乎任何时候你从服务器推出数据时,publish都比method好.

有关聚合不同方法的更多信息,请参见100.

Mongodb相关问答推荐

如何在MongoDB中对两个数组进行分组?

在mongdob中按子文档筛选不起作用

MongoDB对两个串联数组进行排序

仅当特定字段存在于 MongoDB 中时才更新它

Mongodb聚合查找异常值

有没有一种方法可以找到一个文档并通过 Go 更改 mongodb 中的 id/value 来克隆它

查询有关 Go 项目中对象数组的 MongoDb 集合

Mongo 删除最后的文件

更新文档中的数组时,如何在 MongoDB 和 C# 中使用 $push 更新修饰符

如何将 json 字符串编组到 bson 文档以写入 MongoDB?

Mongoose 架构引用和未定义类型ObjectID

mongodump 是否锁定数据库?

单个模式数组中的多个模式引用 - mongoose

如果我在 MongoDB 上使用 LINQ,为什么会失go 性能?

如何在 MongoDB 聚合查询中使用 $hint?

Mongoose.pre('save') 不会触发

在 MongoDB 中快速搜索数十亿个小文档的策略

停止副本集 MongoDB

Spring Data MongoDB - 在哪里以编程方式为 Mongo 集合创建索引?

我需要手动关闭mongoose连接吗?