使用mongo meteor的所有子文档获取不同的对象对

时间:2016-02-04 10:07:05

标签: mongodb meteor

我使用流星并且难以解决这个问题,因为3天。我搜索了stackoverflow,但答案似乎并不能满足我的需求。我有一个销售表,上面有以下数据。

{
"_id" : 1,
"table" : "Table no 2",
"name" : "Hot Coffee",
"quantity" : 2,
"price" : "$10",
"seller" : "User",
"createdAt" : ISODate("2016-01-06T12:57:17.152Z")
},   
{
"_id" : 2,
"table" : "Table no 3A",
"name" : "Hot Coffee",
"quantity" : 1,
"price" : "$10",
"seller" : "User",
"createdAt" : ISODate("2016-02-01T12:58:17.152Z")
},
{
"_id" : 3,
"table" : "Table no 3A",
"name" : "Pizza",
"quantity" : 2,
"price" : "$50",
"seller" : "User",
"createdAt" : ISODate("2016-01-06T12:58:17.152Z")
},
 {
"_id" : 4,
"table" : "2A",
"name" : "Pizza",
"quantity" : 5,
"price" : "$50",
"seller" : "User",
"createdAt" : ISODate("2016-02-02T11:55:17.152Z")
},   

我期待具有所有数量的不同表格名称

{
"name":"Hot Coffee",
"quantity": 3
},
{
"name":"Pizza",
"quantity": 7
}

我尝试了不同的功能,但似乎只显示了一个结果。

1 个答案:

答案 0 :(得分:1)

为此使用 aggregation framework ,但由于Meteor尚未支持聚合,因此您需要安装聚合框架包 - 它不会做任何花哨的事情,只是为你包装一些Mongo方法。

只是流星添加 meteorhacks:aggregate ,您应该开展业务。这将为Meteor添加适当的聚合支持。

现在您需要此管道来实现所需的结果。在mongo shell中,运行以下命令:

var pipeline = [
    {
        "$group": {
            "_id": "$name",
            "quantity": { "$sum": "$quantity" }
        }
    },
    {
        "$project": {
            "name": "$_id", "_id": 0, "quantity": 1
        }
    }
];

db.sales.aggregate(pipeline);

示例输出

{
    "result" : [ 
        {
            "quantity" : 7,
            "name" : "Pizza"
        }, 
        {
            "quantity" : 3,
            "name" : "Hot Coffee"
        }
    ],
    "ok" : 1
}

此聚合操作的作用是使用 $group 管道步骤按name字段对所有文档进行分组,并使用每个不同的组来获取累计总数通过对每个组的数字字段数量使用累加器运算符 $sum 来计算数量。下一个管道 $project 会将以前的管道流文档中的字段重新整形为所需的结构。

在Meteor中,您可以使用以下模式将这些结果发布到客户端的Sales集合,前提是您已将聚合包添加到流星应用程序中:

Meteor.publish('getDistinctSalesWithTotalQuantity', function (opts) {

    var initializing = 1;

    function run(action) {

        // Define the aggregation pipeline ( aggregate(pipeline) )
        var pipeline = [
            {
                "$group": {
                    "_id": "$name",
                    "quantity": { "$sum": "$quantity" }
                }
            },
            {
                "$project": {
                    "name": "$_id", "_id": 0, "quantity": 1
                }
            }
        ];

        Sales.aggregate(pipeline).forEach(function(e){
            this[action]('distinct-sales', e.name, e)
            this.ready()
        });
    };

    // Run the aggregation initially to add some data to your aggregation collection
    run('added');

    // Track any changes on the collection we are going to use for aggregation
    var handle = Sales.find({}).observeChanges({
        added(id) {
            // observeChanges only returns after the initial `added` callbacks
            // have run. Until then, we don't want to send a lot of
            // `self.changed()` messages - hence tracking the
            // `initializing` state.
            if (initializing && initializing--) run('changed');
        },
        removed(id) {
            run('changed');
        },
        changed(id) {
            run('changed');
        },
        error(err) {
            throw new Meteor.Error('Aaaaaaaaah! Grats! You broke it!', err.message)
        }
    });

    // Stop observing the cursor when client unsubs.
    // Stopping a subscription automatically takes
    // care of sending the client any removed messages.
    this.onStop(function () {
        handle.stop();
    });
});

以上观察到变化,如有必要,重新进行汇总。

相关问题