选择没有间隔的年龄计数

时间:2014-07-22 13:56:38

标签: ruby mongodb mongodb-query mongoid aggregation-framework

所以我想要的是写一个查询,它将返回每个年龄段的人数 - 而不是增量。所以那些活着的人数分别为1,2,3,...... 67 ...... 99,......年。

我不熟悉NoSQL,但我知道因为时间在进行,所以必须定期更新/刷新年龄计数。我的想法是拥有一个集合或具有年龄和价值的关键字作为年龄的人数。当一个新人被创建时,它将增加他或她年龄的人数 - 然后正如我之前所说的那样有更新它的东西。

我想弄清楚的是,如果有办法主动获取所有不同年龄段的人数(实时)而没有计数器。或者,如果我必须使用计数器,我怎样才能让数据库自动递增计数器,这样我就不需要与程序交互了?

2 个答案:

答案 0 :(得分:2)

您可以使用MongoDB的聚合框架来实现这一目标。为了使其保持最新,您需要做的是:

  1. 通过从当前日期减去出生日期(ageMillis)来预测dob字段。您将获得一个以毫秒为单位的年龄值。
  2. ageMillis除以一年中的毫秒数(在JavaScript中为31536000000)并将其投影到ageDecimal字段。您不想使用此年龄进行分组,因为它包含小数。
  3. 投放ageDecimal字段和包含年龄小数部分的decimal字段。您可以使用$mod运算符执行此操作。
  4. decimal中减去ageDecimal并将其投影到age字段。这为您提供了年龄的年龄值。
  5. age字段分组,并使用$sum跟踪计数。基本上,您为该年龄的每个文档添加1。
  6. 如果需要,请按age字段排序。
  7. mongo shell中的命令看起来类似于下面的命令,使用JavaScript的Date()对象来获取当前日期。如果你想在Ruby中执行此操作,则必须更改该代码并确保其余部分遵循Ruby驱动程序的语法。

    db.collection.aggregate([
        { "$project" :
            {
                "ageMillis" : { "$subtract" : [ new Date(), "$dob" ]}
            }
        },
        { "$project" :
            {
                "ageDecimal" : { "$divide" : [ "$ageMillis", 31536000000 ]}
            }
        },
        { "$project" :
            {
                "ageDecimal" : "$ageDecimal",
                "decimal" : { "$mod" : [ "$ageDecimal", 1 ]}
            }
        },
        { "$project" :
            {
                "age" : { "$subtract" : [ "$ageDecimal", "$decimal" ]}
            }
        },
        { "$group" : 
            {
                "_id" : { "age" : "$age" },
                "count" : { "$sum" : 1 }
            }
        },
        { "$sort" :
            {
                "_id.age" : 1
            }
        }
    ]);
    

    这可以为您提供所需的结果。请注意,aggregate()方法返回游标。您将不得不迭代它以获得结果。

答案 1 :(得分:1)

聚合框架是最好的方法。 Mongoid通过.collection访问器公开较低级别的集合对象。这允许使用聚合的本机驱动程序实现。

这里的基本数学是:

  

圆满结果:   (从出生日期到现在的差异,以毫秒为单位/     一年中的毫秒数)

将当前Time值输入聚合语句以获取当前年龄

res = Model.collection.aggregate([
  { "$group" => {
    "_id" => {
      "$subtract" => [
        { "$divide" => [
          { "$subtract" => [ Time.now, "$dob" ] },
          31536000000
        ]},
        { "$mod" => [
          { "$divide" => [
            { "$subtract" => [ Time.now, "$dob" ] },
            31536000000
          ]},
          1
        ]}
      ]
    },
    "count" => { "$sum" => 1 }
  }},
  { "$sort" => { "_id" => -1 } }
])

pp res