【问题标题】:Can I make Mongo map reduce count multiple values of an object?我可以让 Mongo map 减少一个对象的多个值吗?
【发布时间】:2018-03-02 00:41:02
【问题描述】:

我有一个集合,我正在尝试按 id 和日期映射 reduce 以生成产品在商店与在线销售的图表。为每个事务创建一个新对象,因此我想将它们减少到给定日期的总数。一个对象看起来像这样:

object
{
      "ProductID": 1
      "Purchase Method": In Store
      "Date": 2018-01-16
      "Count": 5
}

我想要实现的输出是将商店和在线购买组合成一个对象,键是 id 和日期,然后值是每个方法的计数,如下所示:

ProductID: 1
Date: 2018-01-16
[
    {Name: "In store", Count: 3}
    {Name: "Online", Count: 2}
]

我当前的方法是按 ID、日期和购买方法映射对象,因此 reduce 将使用该方法在该日期获取该 id 的总数,但这会导致 id 和日期有两个条目, 1个在店里,1个在网上。这是我的功能的当前状态:

var mapDailySales = function() {
var sale = this;

/*Converts timestamp to just date */
var pad = function pad(n, width, z) {
z = z || '0';
n = n + '';
return n.length >= width ? n : new Array(width - n.length + 1).join(z) + n;
};

var d = sale.Date;
var date = d.getFullYear() + "-" + pad(d.getMonth() + 1, 2, 0) + "-" + pad(d.getDate(), 2, 0);

emit({ProductId: sale.ProductID, Date:date, Method: sale.PurchaseMethod},
{Name: sale.PurchaseMethod, Count: 1})
};


var reduceDailySales = function(key, value) {
var res = {Name: 0, Count: 0};

value.forEach(function(value){
res.Name = value.Name;
res.Count += value.Count;
});

return res; 
};

当前输出如下所示:

{
    "_id" : {
        "ProductId" : 1,
        "Date" : "2018-01-16",
        "Method" : "Online"
    },
    "value" : {
        "Name" : "Online",
        "Count" : 3
    }
}

有没有一种方法可以实现我想要的输出而无需在当前输出上再次缩小地图?

【问题讨论】:

    标签: javascript mongodb mapreduce


    【解决方案1】:

    您可以使用聚合管道而不是 mapReduce 来获取结果,$group 按 ProductID 和 Date,使用 $project 您可以将计数映射到数组

    添加$out 将结果写入新集合,删除它将返回一个游标

    db.prod.aggregate([
        {$group : {
            _id : {ProductID : "$ProductID", Date : "$Date"},
            onlineCount : {$sum : {$cond : [{$eq : ["$PurchaseMethod", "Online"]}, "$Count" , 0]}},
            storeCount : {$sum : {$cond : [{$eq : ["$PurchaseMethod", "In Store"]}, "$Count" , 0]}}
            }
        },
        {$project : {
            _id : 0,
            ProductID : "$_id.ProductID",
            Date : "$_id.Date",
            counts : [{Name: "In Store", Count: "$storeCount"},{Name : "Online", Count: "$onlineCount"}]
        }},
        {$out : "count_stats"}
    ]).pretty()
    

    收藏

    > db.prod.find()
    { "_id" : ObjectId("5a98ce4a62f54862fc7cd1f5"), "ProductID" : 1, "PurchaseMethod" : "In Store", "Date" : "2018-01-16", "Count" : 5 }
    { "_id" : ObjectId("5a98ce4a62f54862fc7cd1f6"), "ProductID" : 1, "PurchaseMethod" : "Online", "Date" : "2018-01-16", "Count" : 2 }
    > 
    

    结果

    > db.count_stats.find()
    { "_id" : ObjectId("5a98d3366a5f43b12a39b4ac"), "ProductID" : 1, "Date" : "2018-01-16", "counts" : [ { "Name" : "In Store", "Count" : 5 }, { "Name" : "Online", "Count" : 2 } ] }
    > 
    

    如果你想使用mapReduce,你可以使用finalize来进一步减少或变换结果

    db.prod.mapReduce(
        <map>,
        <reduce>,
        {
            out: <collection>,
            finalize: <function>
        }
    )
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-15
      • 2018-04-11
      • 2012-09-30
      • 2019-03-07
      • 2017-05-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多