【问题标题】:Mongodb Map Reduce: How can I group the result?Mongodb Map Reduce:如何对结果进行分组?
【发布时间】:2017-11-07 11:28:42
【问题描述】:

我使用的是 map reduce 而不是聚合框架,因为我做了一些字符串操作和值检查。

我有一个查询,它返回具有特定操作系统的设备计数。例如。我已经实现的一个查询返回的结果如下所示:[{"_id":"Android","value":800}, {"_id":"Windows Phone","value":50}]

我已经在使用query 参数来提高性能。现在我想使用 map reduce,结果应该按设备所在的建筑物分组。

数据库结构: 包含多个文档的集合,这些文档具有以下属性:OperatingSystemBuilding

{ “_id”:ObjectId(“5a0174c616bcd022e04fcc43”), “操作系统”:“安卓”, "建筑": xy"}

注意:这是简化的,例如OperatingSystem 包含字符串中的版本号,但我已经在处理它了。

到目前为止我所尝试的:

let map = function () {
    // some manipulation of property values
    // type checks + error handling
    emit({op: this.operatingSystem, this.building], 1); 
}

let reduce = function (key, values) {
        return Array.sum(values);
}

但结果不是我想要的格式:

[{"_id":"Android","value":222}, {"_id":{"operatingSystem":"Windows Phone","building":"xy"},"value":2} , {"_id":{"operatingSystem":"Android","building":"xy"},"value":5}]

结果的问题:关键应该只是建筑物,属性应该是操作系统以及它们对特定建筑物的计数,第一个条目是无用的,不应该是结果的一部分。

结果应该是这样的:

[{"Building": "xy", "deviceCounts": [{"Android": 50}, "Windows Phone": 20}]}, {"Building: zz" //......

如何通过操作系统和在同一属性中构建密钥并保存设备数?

【问题讨论】:

    标签: mongodb mapreduce mongodb-query


    【解决方案1】:

    如果您只需要所需的输出格式(您没有提及您正在执行什么字符串操作),则可以使用聚合框架。例如:

    > db.test.find()
    { "_id": ObjectId(...), "OperatingSystem": "Android", "Building": "xy" }
    { "_id": ObjectId(...), "OperatingSystem": "Android", "Building": "xy" }
    { "_id": ObjectId(...), "OperatingSystem": "Android", "Building": "xy" }
    { "_id": ObjectId(...), "OperatingSystem": "Android", "Building": "xy" }
    { "_id": ObjectId(...), "OperatingSystem": "Android", "Building": "xy" }
    { "_id": ObjectId(...), "OperatingSystem": "Windows Phone", "Building": "xy" }
    { "_id": ObjectId(...), "OperatingSystem": "Windows Phone", "Building": "xy" }
    { "_id": ObjectId(...), "OperatingSystem": "Android", "Building": "zz" }
    { "_id": ObjectId(...), "OperatingSystem": "Android", "Building": "zz" }
    { "_id": ObjectId(...), "OperatingSystem": "Android", "Building": "zz" }
    { "_id": ObjectId(...), "OperatingSystem": "Windows Phone", "Building": "zz" }
    { "_id": ObjectId(...), "OperatingSystem": "Windows Phone", "Building": "zz" }
    

    在本例中,xy 中有 2 个Windows Phone 和 5 个Androidzz 中有 2 个Windows Phone 和 3 个Android

    我发现这个聚合管道会输出所需的格式:

    db.test.aggregate([
        // count occurences of building & operating system combination
        {$group: {_id: {building: '$Building', os: '$OperatingSystem'}, count: {$sum:1}}},
        // group by building
        {$group: {_id: '$_id.building', device: {$push: {k: '$_id.os', v: '$count'}}}},
        // project into the desired format
        {$project: {Building: '$_id', deviceCounts: {$arrayToObject: '$device'}}}
    ])
    

    示例输出为:

    { "_id": "xy", "Building": "xy", "deviceCounts": { "Windows Phone": 2, "Android": 5 } }
    { "_id": "zz", "Building": "zz", "deviceCounts": { "Android": 3, "Windows Phone": 2 } }
    

    请注意,输出中还有一个额外的 _id 字段,因为 MongoDB 要求每个文档都有一个 _id 字段。

    使用的聚合管道 ($arrayToObject) 仅在 MongoDB 3.4 系列中可用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-12-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-13
      • 1970-01-01
      相关资源
      最近更新 更多