mongodb - 从 MongoDB 中获取产品属性的计数

标签 mongodb mapreduce mongodb-query aggregation-framework

我有一个带有属性的产品的 mongo 集合:

{
  "_id" : ObjectId("5888a2860c001d31a1089958"),
  "product_id" : "107",
  "store_id" : 0,
  "attributes" : [{
      "key" : "m",
      "value" : 21,
      "label" : "Mothercare"
    }, {
      "key" : "sp",
      "value" : 10.0,
      "label" : 10.0
    }, {
      "key" : "pr",
      "value" : 2,
      "label" : "150-300"
    }, {
      "key" : "c",
      "value" : 59,
      "label" : "Category 1"
    }, {
      "key" : "c",
      "value" : 86,
      "label" : "Category 2"
    }, {
      "key" : "c",
      "value" : 134,
      "label" : "Category 3"
    }, {
      "key" : "c",
      "value" : 1013,
      "label" : "Category 4"
    }, {
      "key" : "c",
      "value" : 1063,
      "label" : "Category 5"
    }, {
      "key" : "c",
      "value" : 1073,
      "label" : "Category 6"
    }, {
      "key" : "13",
      "value" : 270,
      "label" : "Brown"
    }, {
      "key" : "18",
      "value" : 125,
      "label" : "Girl"
    }, {
      "key" : "19",
      "value" : 298,
      "label" : "0-3 month"
    }, {
      "key" : "19",
      "value" : 299,
      "label" : "3-6 month"
    }, {
      "key" : "19",
      "value" : 300,
      "label" : "6-9 month"
    }, {
      "key" : "19",
      "value" : 301,
      "label" : "9-12 month"
    }]
}

我需要找到快速获取集合中所有属性计数的方法。我尝试过使用 MapReduce:

function map() {
    var max = this.attributes.length;
    var key = {};

    for (var i = 0; i < max; i++) {
        key = {
            key: this.attributes[i]['key'],
            value: this.attributes[i]['value'],
        }

        emit(key, {count: 1}); 
    }
}
function reduce(key, values) {
    var sum = 0;
    values.forEach(function(value) {
        sum += value['count'];
    });
    return {count: sum};
};

但是它很慢:

timeMillis=2420  
counts={ "input" : 18963, "emit" : 221232, "reduce" : 7341, "output" : 1289 }

如何更快地找到所有属性的数量?我需要它用于产品过滤器。也许我必须使用其他集合结构?

我不需要查找属性的总数,我需要查找每个属性的计数,例如:
{ "key": "c", "value": 59 } 有 2345 个产品
{ "key": "m", "value": 21 } 有 258 个产品

最佳答案

运行以下管道将为您提供所需的结果:

db.collection.aggregate([
    { "$unwind": "$attributes" },
    {
        "$group": {
            "_id": {
                "key": "$attributes.key",
                "value": "$attributes.value"
            },
            "counts": { "$sum": 1 }
        }
    }
])

要获得更高效的查询,请使用聚合框架。考虑使用 $project 运行管道 使用 $size 获取每个文档的属性数attributes 数组上的 运算符,然后是最终的 <强> $group 管道,您可以在其中指定一个 null 的 _id 值来计算所有输入文档作为一个整体的累积值,并使用 $sum 计算总计数。 如下:

db.collection.aggregate([
    {
        "$project": {
            "counts": {
                "$size": "$attributes"
            }
        }       
    },
    {
        "$group": {
            "_id": null,
            "counts": { "$sum": "$counts" }
        }
    }
])

以上将返回集合中所有产品的属性总数。


如果您想使用属性计数来过滤产品,请考虑使用 $redact 管道为:

var attributeCount = 12; // for example
db.collection.aggregate([
    {
        "$redact": {
            "$cond": [
                { "$eq": [ { "$size": "$attributes" }, attributeCount ] },
                "$$KEEP",
                "$$PRUNE"
            ]
        }       
    }
])

这相当于 $project 的组合 $match 管道,尽管您不必指定 $project 中的所有字段 管道,如下所示:

db.collection.aggregate([
    {
        "$project": {
            "product_id": 1,
            "store_id": 1,
            "$attributes": 1,
            "counts": {
                "$size": "$attributes"
            }
        }       
    },
    { "$match": { "counts": { "$gte": attributeCount } } }
])

关于mongodb - 从 MongoDB 中获取产品属性的计数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41868225/

相关文章:

mongodb - 在 MongoDB 中,您能从 shell 中看到命令行参数吗?

regex - 尽管 : elif: else,但使用正则表达式的 PyMongo 查询不返回任何内容

mongodb - MongoDB 聚合上是否可以有多个分组的 "$or"运算符?

MongoDB 如何获取子文档属性等于某个值的不同子文档列表?

javascript - 使用 Mongodb native 驱动程序以编程方式切换 boolean 值

mongodb - 一般 MongoDB 性能故障排除

json - JSON MapReduce 错误

MongoDB count with query 返回的记录多于 count all

apache - Hadoop生态系统部署步骤

hadoop - "Bigdata"有多大数据?