【问题标题】:Querying last 30 days date range with Mongoid and Ruby?使用 Mongoid 和 Ruby 查询最近 30 天的日期范围?
【发布时间】:2011-12-08 08:56:14
【问题描述】:

如何使用 Mongoid 和 Ruby 查询日期范围(比如从现在开始的最后 30 天)?

我需要得到一个数组或哈希,如下所示:

{
    15 => 300,
    14 => 23,
    13 => 23
    ...
    30 => 20  # Goes over into previous month
    28 => 2
}

我目前正在使用 DateTime 实例以及 unix timestamp Integer 字段存储每个文档。

上述哈希中的键是天数,值是那些天所有销售额的总和。

有什么想法吗?

【问题讨论】:

    标签: ruby mongodb mongoid date range


    【解决方案1】:

    有一个更简单的方法:

    Sale.where(created_at: (30.days.ago..Time.now))
    

    调整时间范围以适应。

    【讨论】:

    • 这需要 .days.ago 部分的 ActiveSupport
    • 我认为您不能以这种方式使用哈希语法添加多个参数。不过可能是错的。
    • @AshBlue - 它是 Range 类型的单个参数。 ruby-doc.org/core-2.0.0/Range.html
    • ruby 中的 Range 非常昂贵。虽然语法不错,但我会选择 gtelte
    • @oma - 您能否提供一些信息/链接,为什么 ruby​​ 范围很昂贵,尤其是在这种情况下(mongodb 查询)?
    【解决方案2】:

    这是在 ruby​​land 中的全部操作方法:

    sales_by_date = Hash.new(0)
    
    Sale.where(:created_at.gte => (Date.today - 30)).order_by(:created_at, :desc).each do |s|
      sales_by_date[s.created_at.strftime("%m-%d")] += 1
    end
    

    这将使用“月-日”键创建一个哈希,原因是某些月份的天数少于 30 天,如果查询始终为 30,则会导致键冲突。

    如果您想要不同的范围,请更改查询:

    # Between 10 and 20 days ago
    start_day       = 10
    end_day         = 20
    
    Sale.where(:created_at.gte => (Date.today - end_day), :created_at.lte => (Date.today - start_day))
    

    created_at 更改为您的日期时间字段的名称。

    【讨论】:

    • 如果使用2012-06-16 而不是(Date.today - 30) 那么如何编写查询?
    • @harsh4u:首先将字符串转换为 Date 对象。 Date.parse("2012-06-16")
    • 这远非完美的解决方案,下面的答案要好得多。
    • Sale.where(:end_date.gte => (Date.today), :begin_date.lte => (Date.today)).order(begin_date: :desc)
    【解决方案3】:

    您也可以使用between 方法编写查询,例如:

    Sale.between(created_at: (30.days.ago..Time.now))
    

    【讨论】:

      【解决方案4】:

      如果您忘记在模型中添加时间戳怎么办? :(

      没问题!只需使用BSON:ObjectId中的时间戳

      在过去 30 天内获得销售额。

      Sale.where(:id.gte => Moped::BSON::ObjectId.from_time((Date.today - 30).to_time))
      

      由于id 字段是索引,这很可能是最快的查询。

      需要日期范围?蛋糕。

      获取上个月的销售额。

      Sale.and(
        {:id.gte => Moped::BSON::ObjectId.from_time((Date.today.prev_month.beginning_of_month).to_time)},
        {:id.lte => Moped::BSON::ObjectId.from_time((Date.today.prev_month.end_of_month).to_time)}
      )
      

      当然,这个例子假设 Rails 日期助手......

      【讨论】:

      • 我认为这是更好的答案。它比较困难,但它有很好的性能。谢谢!
      【解决方案5】:

      例如,您可以通过使用仅发出相关条目(日期值大于您给它的任何条件的条目)的映射函数对您的集合进行 map_reduce 调用来实现此目的。

      试试这样的:

      map = "function () { emit( {this.date.getDate(), {}} )}"
      reduce = "function (key, values) { return {date: key, count: values.length } }"
      
      collection.map_reduce(map, reduce, {query: {"date": {"$gt": 30.days.ago } } })
      

      这可能行得通。

      【讨论】:

        猜你喜欢
        • 2015-07-01
        • 2011-08-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-05-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多