【问题标题】:How to get (or aggregate) distinct keys of array in MongoDB如何在 MongoDB 中获取(或聚合)数组的不同键
【发布时间】:2015-06-27 02:22:12
【问题描述】:

我正在尝试让 MongoDB 在不知道键的情况下通过具有不同键值对的数组为我聚合(只需简单的求和即可。)

示例文档:

{data: [{a: 3}, {b: 7}]}
{data: [{a: 5}, {c: 12}, {f: 25}]}
{data: [{f: 1}]}
{data: []}

所以基本上每个文档(或者实际上是数组)可以有 0 个或多个条目,我不知道这些对象的键,但我想对这些键的值求和和平均。

现在我只是加载一堆文档并自己在 Node 中完成,但我想将这项工作卸载到 MongoDB。

我知道我可以先解开这些,但如何从那里着手呢?如果我不知道键,如何求和/平均/最小/最大值?

【问题讨论】:

    标签: mongodb aggregation-framework


    【解决方案1】:

    如果您不知道密钥或无法做出合理的有根据的猜测,那么您基本上无法继续使用聚合框架。您可以提供“所有密钥”以供考虑,但我怀疑您的实际数据看起来更像这样:

    { "data": [{ "film": 10 }, { "televsion": 5 },{ "boardGames": 1 }] }
    

    所以在这里找出所有“键名”然后将其扔到聚合语句中没有什么意义。

    不过,为了记录,“这就是为什么你没有像这样构建数据存储的原因”。此处的“电影”等信息不应用作“关键”名称,因为它是有用的“数据”,可以在数据库系统中搜索,最重要的是“索引”。

    所以你的数据应该看起来像这样:

    { 
        "data": [
            { "type": "film", "value": 10 },
            { "type": "televsion", "valule": 5 },
            { "type": "boardGames", "value": 1 }
        ]
    }
    

    那么聚合语句就很简单了,其他很多事情也一样:

    db.collection.aggregate([
        { "$unwind": "$data" },
        { "$group": {
            "_id": null,
            "sum": { "$sum": "$data.value" },
            "avg": { "$avg": "$data.value" }
        }}
    ])
    

    但是由于文档中键名是不断变化的,并且没有统一的结构,那么就需要在服务器端进行 JavaScript 处理来遍历这些键,也就是 mapReduce:

    db.collection.mapReduce(
        function() {
            this.data.forEach(function(data) {
                Object.keys(data).forEach(function(key) {
                    emit(null,data[key]); // emit the value regardless of key name
                });
            });
        },
        function(key,values) {
            return Array.sum(values);     // Just summing for example
        },
        { "out": { "inline": 1 } }
    )
    

    当然,这里的 JavaScript 执行将比聚合框架可用的本机编码运算符慢得多。

    所以这应该是一个关于为什么在数据库中存储数据时不使用“数据”作为“键名”的惨痛教训。聚合框架与标准结构一起工作并且速度很快,回退到 JavaScript 处理更灵活,但成本主要在于速度和其他功能。

    【讨论】:

    • 拍拍额头——现在是时候重写所有内容了,因为我意识到我将“数据”放在了密钥的名称中!谢谢!
    猜你喜欢
    • 2019-07-15
    • 1970-01-01
    • 1970-01-01
    • 2021-02-08
    • 1970-01-01
    • 2021-09-30
    • 1970-01-01
    • 1970-01-01
    • 2021-06-18
    相关资源
    最近更新 更多