使用mongodb中的聚合获取具有最大值的所有文档

时间:2015-10-27 07:00:56

标签: mongodb mongodb-query aggregation-framework

我想获取特定字段值最高的“所有文档”,而不是另一个字段的组。

考虑以下数据:

_id:1, country:india,  quantity:12,  name:xyz
_id:2, country:USA,    quantity:5,   name:abc
_id:3, country:USA,    quantity:6,   name:xyz
_id:4, country:india,  quantity:8,   name:def
_id:5, country:USA,    quantity:10,  name:jkl
_id:6, country:india,  quantity:12,  name:jkl

答案应该是

country:india max-quantity:12
name xyz
name jkl 

country:USA max-quantity:10
name jkl

我已经尝试了几个查询,但是我只能获得没有名称的最大值,或者我可以分组,但它会显示所有值。

db.coll.aggregate({$group:{_id:"$country","maxQuantity":{$max:"$quantity"}}})
例如上面的例子将给出每个国家的最大数量但是如何与其他领域结合以显示最大数量的所有文件。

3 个答案:

答案 0 :(得分:11)

如果您想保留文档信息,那么您基本上需要将$push放入数组中。但是,当然,然后拥有$max值,您需要过滤数组内容以仅匹配匹配的元素:

db.coll.aggregate([
    { "$group":{ 
        "_id": "$country",
        "maxQuantity": { "$max": "$quantity" },
        "docs": { "$push": {
            "_id": "$_id",
            "name": "$name",
            "quantity": "$quantity"
        }}
    }},
    { "$project": {
        "maxQuantity": 1,
        "docs": {
            "$setDifference": [
               { "$map": {
                   "input": "$docs",
                   "as": "doc",
                   "in": {
                       "$cond": [ 
                           { "$eq": [ "$maxQuantity", "$$doc.quantity" ] },
                           "$$doc",
                           false
                       ]
                   }
               }},
               [false]
            ]
        }
    }}
])

因此,您将所有内容存储在一个数组中,然后测试每个数组成员以查看它的值是否与记录为最大值的值匹配,丢弃任何不存在的值。

我会在数组文档中保留_id值,因为这会使它们“唯一”,并且在过滤掉值时不会受$setDifference的负面影响。但当然,如果“名称”始终是唯一的,则不需要它。

您也可以从$map返回您想要的任何字段,但我只是返回整个文档。

请记住,这具有不超过16MB的BSON大小限制的限制,因此对于小数据样本是可以的,但是产生可能大的列表的任何东西(因为你不能预先过滤数组内容)会更好使用单独的查询处理以查找“max”值,使用另一个查询来获取匹配的文档。

答案 1 :(得分:3)

我知道如果你改变特定的国家范围,如何更简单地完成类似的任务:

[
{"$match":{"name":{"$in":["USA","india"]}}}, // stage one
{ "$sort": { "quanity": -1 }}, // stage three
{"$limit":2 } // stage four - count equal ["USA","india"] length
]

如果您需要所有国家/地区,请尝试关注,但不保证我:

[
{"$project": {
    "country": "$country",
    "quantity": "$quantity",
    "document": "$$ROOT" // save all fields for future usage

}},
{ "$sort": { "quantity": -1 }},
{"$group":{"_id":{"country":"$country"},"original_doc":{"$first":"$document"} }}
]

答案 2 :(得分:1)

另一种方式可以是:

<input type="image" src="images/rock.svg" class="rock">
<input type="image" src="images/scissor.svg" class="scissor">
<input type="image" src="images/paper.svg" class="paper">