草庐IT

mongodb - 按日期间隔分组

coder 2023-10-28 原文

我有一个包含这样文档的集合:

{ datetime: new Date(), count: 1234 }

我想按24 小时7 天30 天 间隔获取计数 的总和。

结果应该是这样的:

{ "sum": 100,  "interval": "day" }
{ "sum": 700,  "interval": "week" }
{ "sum": 3000, "interval": "month" }

用更抽象的术语来说,我需要根据多个条件(在本例中为多个时间间隔)对结果进行分组

MySQL 的等价物是:

SELECT 
    IF (time>CURRENT_TIMESTAMP() - INTERVAL 24 HOUR, 1, 0) last_day,
    IF (time>CURRENT_TIMESTAMP() - INTERVAL 168 HOUR, 1, 0) last_week,
    IF (time>CURRENT_TIMESTAMP() - INTERVAL 720 HOUR, 1, 0) last_month,
    SUM(count) count
FROM table
GROUP BY    last_day,
            last_week,
            last_month

最佳答案

date aggregation operators可用于 MongoDB 的聚合框架。例如 $dayOfYear运算符用于从日期中获取该值以用于分组:

db.collection.aggregate([
    { "$group": {
        "_id": { "$dayOfYear": "$datetime" },
        "total": { "$sum": "$count" }
    }}
])

或者您可以改用日期数学方法。通过应用纪元日期,您可以将日期对象转换为可以应用数学的数字:

db.collection.aggregate([
    { "$group": {
        "_id": { 
            "$subtract": [
                { "$subtract": [ "$datetime", new Date("1970-01-01") ] },
                { "$mod": [
                    { "$subtract": [ "$datetime", new Date("1970-01-01") ] },
                    1000 * 60 * 60 * 24
                ]}
            ]
        },
        "total": { "$sum": "$count" }
    }}
])

如果您想要的是从当前时间点开始的间隔,那么您想要的基本上是日期数学方法,并通过 $cond 在某些条件中工作。运算符(operator):

db.collection.aggregate([
    { "$match": {
        "datetime": { 
            "$gte": new Date(new Date().valueOf() - ( 1000 * 60 * 60 * 24 * 365 ))
        }
    }},
    { "$group": {
        "_id": null,
        "24hours": { 
            "$sum": {
                "$cond": [
                    { "$gt": [
                        { "$subtract": [ "$datetime", new Date("1970-01-01") ] },
                        new Date().valueOf() - ( 1000 * 60 * 60 * 24 )
                    ]},
                    "$count",
                    0
                ]
            }
        },
        "30days": { 
            "$sum": {
                "$cond": [
                    { "$gt": [
                        { "$subtract": [ "$datetime", new Date("1970-01-01") ] },
                        new Date().valueOf() - ( 1000 * 60 * 60 * 24 * 30 )
                    ]},
                    "$count",
                    0
                ]
            }
        },
        "OneYear": { 
            "$sum": {
                "$cond": [
                    { "$gt": [
                        { "$subtract": [ "$datetime", new Date("1970-01-01") ] },
                        new Date().valueOf() - ( 1000 * 60 * 60 * 24 * 365 )
                    ]},
                    "$count",
                    0
                ]
            }
        }
    }}
])

它本质上与 SQL 示例的方法相同,其中查询有条件地评估日期值是否在要求的范围内,并决定是否将该值添加到总和中。

这里添加的是附加的 $match阶段限制查询仅对可能在您要求的最大一年范围内的那些项目起作用。这使得它比提供的 SQL 好一点,因为可以使用索引来过滤掉那些值,并且您不需要通过集合中的不匹配数据来“暴力破解”。

$match 限制输入总是个好主意使用聚合管道时。

关于mongodb - 按日期间隔分组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27750974/

有关mongodb - 按日期间隔分组的更多相关文章

  1. ruby-on-rails - 按天对 Mongoid 对象进行分组 - 2

    在控制台中反复尝试之后,我想到了这种方法,可以按发生日期对类似activerecord的(Mongoid)对象进行分组。我不确定这是完成此任务的最佳方法,但它确实有效。有没有人有更好的建议,或者这是一个很好的方法?#eventsisanarrayofactiverecord-likeobjectsthatincludeatimeattributeevents.map{|event|#converteventsarrayintoanarrayofhasheswiththedayofthemonthandtheevent{:number=>event.time.day,:event=>ev

  2. ruby - 在 Ruby 中创建按公共(public)键值分组的新哈希 - 2

    假设我有一个在Ruby中看起来像这样的哈希:{:ie0=>"Hi",:ex0=>"Hey",:eg0=>"Howdy",:ie1=>"Hello",:ex1=>"Greetings",:eg1=>"Goodday"}有什么好的方法可以将它变成如下内容:{"0"=>{"ie"=>"Hi","ex"=>"Hey","eg"=>"Howdy"},"1"=>{"ie"=>"Hello","ex"=>"Greetings","eg"=>"Goodday"}} 最佳答案 您要求一个好的方法来做到这一点,所以答案是:一种您或同事可以在六个月后理解

  3. arrays - 如何在下面的示例中将两个值数组分组为 n 个值数组? - 2

    我已经有很多两个值数组,例如下面的例子ary=[[1,2],[2,3],[1,3],[4,5],[5,6],[4,7],[7,8],[4,8]]我想把它们分组到[1,2,3],[4,5],[5,6],[4,7,8]因为意思是1和2有关系,2和3有关系,1和3有关系,所以1,2,3都有关系我如何通过ruby​​库或任何算法来做到这一点? 最佳答案 这是基本Bron–Kerboschalgorithm的Ruby实现:classGraphdefinitialize(edges)@edges=edgesenddeffind_maximum_

  4. ruby - 如何将相同的相邻数字分组 - 2

    如果至少有两个相邻的数字相同,格式为,我需要打包.这是我的输入:[2,2,2,3,4,3,3,2,4,4,5]以及预期的输出:"2:3,3,4,3:2,2,4:2,5"到目前为止我试过:a=[1,1,1,2,2,3,2,3,4,4,5]a.each_cons(2).any?do|s,t|ifs==t如果相等,也许可以尝试计数器,但那是行不通的。 最佳答案 您可以使用Enumerable#chunk_while(如果你使用的是Ruby>=2.3):a.chunk_while{|a,b|a==b}.flat_map{|chunk|chu

  5. 多种方法期间的 Ruby 救援异常 - 2

    我构建了一个简单的银行应用程序,它能够执行通常的操作;充值、提现等我的Controller方法执行这些操作并拯救由帐户或其他实体引发的异常。以下是Controller代码中使用的一些方法:defopen(type,with:)account=createtype,(holders.findwith)addaccountinit_yearly_interest_foraccountboundary.renderAccountSuccessMessage.new(account)rescueItemExistError=>messageboundary.rendermessageendde

  6. ruby-on-rails - 如何在记录更新期间从验证中排除密码字段? ( rails 3.0.4, ruby 1.9.2) - 2

    我有一个允许更新用户记录的表单。它包含:password和:password_confirmation字段,但我不希望在数据库中已存储加密密码时对它们运行验证。View文件中的字段:'ConfirmPassword'%>在互联网上搜索时,我发现了这段代码,我认为它是针对以前版本的Ruby/Rails的。(我会把它放在我的用户模型中。)validates_presence_of:password,:on=>create由于我的用户模型中密码验证的语法不同(如下),我对我需要的语法感到困惑。validates:password,:presence=>true,:confirmation=>

  7. ruby - 如何在 Ruby 中将数字分组到不同的桶中 - 2

    我有一个文件,每一行都有数字:010110101311010113114311010431420我想要一个包含每个数字出现次数的散列,在这种情况下:{0101=>2,1010=>2,1311=>2,431=>2,420=>1}我该怎么做? 最佳答案 简单的一行代码,给定一个数组items:items.inject(Hash.new(0)){|hash,item|hash[item]+=1;hash}工作原理:Hash.new(0)创建一个新的Hash,其中访问未定义的键返回0。inject(foo)使用给定的block遍历数组。对于

  8. ruby-on-rails - 在条件路由期间未在 Rails 3 中设置 request.subdomain - 2

    我正在尝试根据RyanBatesscreencastonsubdomains在Rails3中设置子域.但是它对我不起作用。我有以下设置:#routes.rbconstraints(Subdomain)doget'devices'=>'devices#all'end#lib/subdomain.rbclassSubdomaindefself.matches?(request)#binding.pryrequest.subdomain.present?&&request.subdomain=="admin"endend加载urladmin.localhost:3000/devices应该将

  9. ruby-on-rails - Ruby On Rails Mongoid 分组依据 - 2

    对于按日期分组,我使用了group_by方法。Example:Product.all.group_by{|d|d.created_at}#returnHash但是kaminari不支持Hash。我使用Mongoid,我需要通过页面导航(kaminari)按日期分组。怎么做到的? 最佳答案 Kaminari只支持数组分页例如Kaminari.paginate_array(an_array).page(1).per(10)group_by不是mongoid方法,它是Array的方法,它是对内存中的所有数据进行分组。为了使用mongoid

  10. ruby - 按相似性对字符串进行分组 - 2

    我有一个字符串数组,数量不多(可能几百个)但通常很长(几百个字符)。这些字符串通常是无意义的,并且彼此不同。但是在一组这样的字符串中,可能300个中有5个具有很大的相似性。事实上,它们是相同的字符串,不同的是格式、标点符号和一些单词..我怎样才能算出那组字符串?顺便说一句,我正在用ruby​​编写,但如果没有别的,伪代码算法就可以了。谢谢 最佳答案 假设您不担心每个单词的拼写错误或其他错误,您可以执行以下操作:构建一个倒排索引,它基本上是一个以单词为键的散列,指向包含该单词的字符串的指针列表(如何处理重复出现由您决定)。要确定与给定

随机推荐