【问题标题】:Complex aggregate command MongoDB复杂的聚合命令 MongoDB
【发布时间】:2013-12-18 21:21:58
【问题描述】:

我在 Mongo 数据库中有大量文档,其结构如下:

{
    "_id" : {
        "birthDate" : "1978-08-09",
        "name" : "Peter"
},
    "value" : {
        "types" : {
            "euro" : 90,
            "unknown" : 2,
            "dollar" : 3
        }
    }
}

并非所有文档都包含所有类型(即:其中一些只有 euro 或没有 unknown 字段)。

我想用聚合框架来统计每个type 的出现次数。

我有这个:

db.collection.aggregate({$match: {_id : {name:"John"}}}, {$group: {_id: '', euro: {$sum: '$value.types.euro'}, dollar: {$sum: '$value.types.dollar'}, unknown: {$sum: '$value.types.unknown'}}})

但它正在返回:

{ "result" : [ ], "ok" : 1 }

我的问题是:如何使用 Mongo 的聚合框架计算每个 cointype 以获取特定的 name?是否也可以获取表单中每个名称的列表:

"result" : [
    {
        "name" : "Peter",
        "dollar" : 1,
        "euro" : 12,
        "unknown" : 4

    }
]

"result" : [
    {
        "name" : "John",
        "dollar" : 4,
        "euro" : 10,
        "unknown" : 3

    }
]

我正在使用带有 Java 驱动程序的 MongoDB,所以如果答案是 Java 代码,那将是完美的。

【问题讨论】:

    标签: mongodb aggregation-framework


    【解决方案1】:

    您可以使用以下查询按名称和计数硬币分组:

    db.collection.aggregate(
      {$group : {_id : "$_id.name", 
                 dollar : {$sum : "$value.types.dollar"}, 
                 euro : {$sum : "$value.types.euro"}, 
                 unknown : {$sum : "$value.types.unknown"}}}
    )
    

    此外,如果您想查找特定人的硬币数量,您可以使用以下查询:

    db.collection.aggregate(
      {$match : {"_id.name" : "John"}},
      {$group : {_id : "$_id.name", 
                 dollar : {$sum : "$value.types.dollar"}, 
                 euro : {$sum : "$value.types.euro"}, 
                 unknown : {$sum : "$value.types.unknown"}}}
    )
    

    【讨论】:

    • 这就是我想要的。现在我想知道:是否可以只取两个日期之间的生日结果?即第一个请求的结果完全相同,但仅限于例如 1980-07-05 和 1985-08-05 之间的结果
    • 您可以将 $match 查询更新为 {$match : {"_id.name" : "John", "_id.birthDate" : {$gte : "1980-07-05", $lte : "1985-08-05"}}}
    • 很好,现在的问题是日期实际上是这样存储的:ISODate("1980-08-05T22:00:00Z")。那些 $gte 似乎并没有真正起作用,当我将 $match 更新为{$match@987654 : : 1 } 987654334@:"John","_id.birthDate":{$gte:'ISODate("1980-07-5")','ISODate("1980-07-5")',$lte:'ISODate("1985-08-05")'}}}
    【解决方案2】:

    要为特定的name 计算每个cointype,您可以这样做:

    db.collection.aggregate([
    {
        $match: {'_id.name' : "John"}
    }, 
    {
        $project: {
            _id: 1,
            euro: {$cond: [ { $eq: [ '$value.types.euro', undefined ]} , 0, 1 ]},
            dollar: {$cond: [  { $eq: [ '$value.types.dollar', undefined ]} , 0, 1 ]},
            unknown: {$cond: [ { $eq: [ '$value.types.unknown', undefined ]}, 0, 1 ]}
        }  
    },
    {
        $group: {_id: "$_id.name", euro: {$sum: '$euro'}, dollar: {$sum: '$dollar'}, unknown: {$sum: '$unknown'}}
    }
    ])
    

    【讨论】:

    • 这应该等同于@parvin 写的第二个查询吗?结果大相径庭
    • 不,它不等同于@parvin 写的第二个查询。我的查询计算每种类型(欧元、美元和未知)在 _id.name = 'John' 的所有文档中出现的次数。它不是类型值的 $sum。我希望很清楚,我的英语不是很好:)
    • 好的,我明白了!那时我正在寻找更多@parvin 的。不过还是谢谢
    猜你喜欢
    • 2019-11-04
    • 2014-10-21
    • 2018-10-31
    • 2021-03-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多