按日期按年龄段分组

时间:2018-11-22 09:47:21

标签: mongodb mongodb-query aggregation-framework

我有一个结构:

stage ('Reports') {
    step([$class: 'FindBugsPublisher', canComputeNew: false, canRunOnFailed: true, defaultEncoding: '', excludePattern: '', failedTotalHigh: '0', failedTotalNormal: '200', failedTotalLow: '350', healthy: '', includePattern: '', pattern: '**/spotbugsXml.xml', unHealthy: ''])
    step([$class: 'CheckStylePublisher', canComputeNew: false, canRunOnFailed: true, defaultEncoding: '', healthy: '', pattern: '**/maven_checks.xml ',failedTotalHigh: '0', failedTotalNormal: '0',failedTotalLow: '0', unHealthy: ''])
    step([$class: 'WarningsPublisher', canComputeNew: false, canResolveRelativePaths: false, consoleParsers: [[parserName: 'Maven'], [parserName: 'userdef-protobuf'], [parserName: 'userdef-xtend']], defaultEncoding: '', excludePattern: '', healthy: '', includePattern: '', messagesPattern: '', unHealthy: ''])
} 

我需要按user_age_group分组数据。我有一个预定义的年龄组:

[
            {
                "_id": {
                    "question": "Voluptatem perferendis voluptas ex.",
                    "option": "Eligendi ratione fuga autem fugiat velit quo.",
                    "user_dob": {
                        "$date": {
                            "$numberLong": "1306281600000"
                        }
                    }
                },
                "total_votes": 1
            },
            {
                "_id": {
                    "question": "Voluptatem perferendis voluptas ex.",
                    "option": "Eligendi ratione fuga autem fugiat velit quo.",
                    "user_dob": {
                        "$date": {
                            "$numberLong": "22118400000"
                        }
                    }
                },
                "total_votes": 1
            }, {...}, ...
]

或者甚至说,对于所有这些age_group,我已经计算出了$ from和$ to变量。

最后,我需要获得下一个结构:

'age_groups' => [
        '0-14 years' => ['from' => 0, 'to' => 14],
        '15-24 years' => ['from' => 15, 'to' => 24],
        '25-54 years' => ['from' => 25, 'to' => 54],
        '55-64 years' => ['from' => 55, 'to' => 64],
        '65 years and over' => ['from' => 65, 'to' => 999]
    ]

似乎我需要添加一些计算所得的属性,然后按其添加组。但是我不知道该怎么做...希望有人能帮助我。

1 个答案:

答案 0 :(得分:1)

您可以在此处使用$switch运算符进行翻译,将当前日期与存储日期中的$year进行比较。

为了嵌套数组,您将多次调用$group

db.collection.aggregate([
  { "$group": {
    "_id": {
      "question": "$_id.question",
      "option": "$_id.option",
      "age_group": {
        "$let": {
          "vars": { 
            "age": {
              "$subtract": [
                { "$year": new Date() },
                { "$year": "$_id.user_dob" }
              ]
            }
          },
          "in": {
            "$switch": {
              "branches": [
                {
                  "case": { "$lte": [ "$$age", 14 ] },
                  "then": "0-14 years",
                },
                {
                  "case": { "$lte": [ "$$age", 24 ] },
                  "then": "15-24 years",
                },
                {
                  "case": { "$lte": [ "$$age", 54 ] },
                  "then": "25-54 years",
                },
                {
                  "case": { "$lte": [ "$$age", 64 ] },
                  "then": "55-64 years",
                }
              ],
              "default": "65 years and over"
            }
          }
        }
      }
    },
    "total_votes": { "$sum": "$total_votes" }
  }},
  { "$group": {
    "_id": {
      "question": "$_id.question",
      "option": "$_id.option"
    },
    "votes_by_age": {
      "$push": {
        "age_group": "$_id.age_group",
        "total_votes": "$total_votes"
      }
    },
    "total_votes": { "$sum": "$total_votes" }
  }},
  { "$group": {
    "_id": "$_id.question",
    "options": {
      "$push": {
        "option": "$_id.option",
        "votes_by_age": "$votes_by_age",
        "total_votes": "$total_votes"
      }
    },
    "total_votes": { "$sum": "$total_votes" }
  }}
])

所提供数据的输出:

{
        "_id" : "Voluptatem perferendis voluptas ex.",
        "options" : [
                {
                        "option" : "Eligendi ratione fuga autem fugiat velit quo.",
                        "votes_by_age" : [
                                {
                                        "age_group" : "25-54 years",
                                        "total_votes" : 1
                                },
                                {
                                        "age_group" : "0-14 years",
                                        "total_votes" : 1
                                }
                        ],
                        "total_votes" : 2
                }
        ],
        "total_votes" : 2
}

请注意,问题的一部分似乎包含PHP代码,因此对于MongoDB\BSON\UTCDatetime(time() * 1000)的基于JavaScript的外壳,请使用PHP new Date()和MongoDB驱动程序函数来代替time()将其包装为BSON日期。

$let是这样的,因此您不会在$switch情况下每次引用相同的表达式时都重复该表达式。如图所示,"vars"是通过$$前缀声明和引用的。{p}

每个$group会逐渐删除一部分键,因此会累积内容,然后随着键的移动通过$push移到数组中。每个级别上额外的"$$age"应该使这种积累如何工作