MongoDB 最小/最大聚合

标签 mongodb mapreduce aggregation-framework

我有具有这种简化架构的文档:

{
   positon: 10,
   value: 5,
   count: 3
}

我想要计算的是按位置对这些文档进行分组,并找到最大,其中计数大于4但具有 小于计数小于 4 的最小

这是我所做的,但它不起作用:

{ $group: { 
          _id: {
                   position: "$position",
                 },
          result: {$max: { $cond: [ {$and: [  {$gte: ["$count", 4]}, 
                                              {$lt: ["$value", {$min: { $cond: [ {$lt: ["$count", 4]}, 
                                                                                 { value: "$value" },  
                                                                                 10]
                                                                      }                                                              
                                                               }]
                                             }]},
                                    { value: "$value", nb: "$count"}, 
                                    0] 
                        }
                }
          }
}

有人说 $min 是一个无效的运算符,我不知道如何编写正确的聚合函数。运行mapreduce会更好吗?

如果我有这些文件

{Position: 10, value: 1, count 5}
{Position: 10, value: 3, count 3}
{Position: 10, value: 4, count 5}
{Position: 10, value: 7, count 4}

我希望结果是

{Position: 10, value: 1, count 4}

因为它是计数大于 4 的“值”的最大值,而且因为值 3 只有 3 个计数,所以值 4 不是我要查找的值。

最佳答案

至少可以说这有点拗口,但我会再解释一下:

你想要:

For each "Position" value find the document whose "value" is less than the the largest "value" of the document with a "count" of less than four, whose own "count" is actually greater than 4.

这读起来就像一道数学考试题,旨在让你混淆逻辑。但是,捕获这个含义之后,您可以通过以下步骤执行聚合:

db.positions.aggregate([
    // Separate the values greater than and less than 4 by "Position"
    { "$group": {
        "_id": "$Position",
        "high": { "$push": {
            "$cond": [
                { "$gt": ["$count", 4] },
                { "value": "$value", "count": "$count" },
                null
            ]
        }},
        "low": { "$push": {
            "$cond": [
                { "$lt": ["$count", 4] },
                { "value": "$value", "count": "$count" },
                null
            ]
        }}
    }},

    // Unwind the "low" counts array
    { "$unwind": "$low" },

    // Find the "$max" value from the low counts
    { "$group": {
        "_id": "$_id",
        "high": { "$first": "$high" },
        "low":  { "$min": "$low.value" }
    }},

    // Unwind the "high" counts array
    { "$unwind": "$high" },

    // Compare the value to the "low" value to see if it is less than
    { "$project": {
         "high": 1,
         "lower": { "$lt": [ "$high.value", "$low" ] }
    }},

    // Sorting, $max won't work over multiple values. Want the document.
    { "$sort": { "lower": -1, "high.value": -1 } },

    // Group, get the highest order document which was on top
    { "$group": {
        "_id": "$_id",
        "value": { "$first": "$high.value" },
        "count": { "$first": "$high.count" }
    }}
])

因此,从一组文档来看:

{ "Position" : 10, "value" : 1, "count" : 5 }
{ "Position" : 10, "value" : 3, "count" : 3 }
{ "Position" : 10, "value" : 4, "count" : 5 }
{ "Position" : 10, "value" : 7, "count" : 4 }

在这种情况下,仅返回第一个,因为它的值小于“计数三”文档,而它自己的计数大于 4。

{ "_id" : 10, "value" : 1, "count" : 5 }

我确信这就是您的实际意思。

所以$min的应用和 $max实际上仅适用于从分组范围之外的文档中获取离散值时。如果您对文档或整个文档中的多个值感兴趣,那么您将排序并获得 $first$last分组边界上的条目。

聚合比 mapReduce 快得多,因为它使用 native 代码而不调用 JavaScript 解释器。

关于MongoDB 最小/最大聚合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23208818/

相关文章:

node.js - Mongoose - 如何从对象 ID 数组中查找集合

javascript - 我应该把这行代码放在 Meteor 新的文件结构中的什么位置呢?

javascript - 从 MongoDB 中的嵌套数组中查找公共(public)属性

hadoop - 如何在mapreducer和hbase之间拆分内存

elasticsearch - Elasticsearch通过下一个/上一个数组项进行过滤/聚合

ruby-on-rails - Mongoid embeds_many 和 has_many 到同一个模型

hadoop - MapReduce 程序性能测试

hadoop - 在 hive 中排名

javascript - 将多个文档数组展开为新文档

mongodb - 如何查找数组中的重复元素(一个文档)?