Запрашиваете диапазон дат за последние 30 дней с Mongoid и Ruby? - PullRequest
12 голосов
/ 15 октября 2011

Как мне выполнить запрос диапазона дат (скажем, последние 30 дней с этого момента) с Mongoid и Ruby?

Мне нужно получить массив или хэш, как показано ниже:

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

В настоящее время я храню каждый документ с экземпляром DateTime, а также целочисленным полем метки времени unix.

Ключами в приведенном выше хеше являются дни, а значения - сумма всех продаж за эти дни.

Есть идеи?

Ответы [ 5 ]

28 голосов
/ 16 июня 2012

Есть более простой способ:

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

Настройка временного диапазона в соответствии с требованиями.

20 голосов
/ 16 октября 2011

Вот как все это сделать в rubyland:

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 на любое имя вашего поля даты и времени.

4 голосов
/ 03 сентября 2014

Вы также можете написать запрос, используя метод between, например:

Sale.between(created_at: (30.days.ago..Time.now))
2 голосов
/ 04 июня 2014

Что если вы забыли поставить метки времени в своей модели? (

Нет проблем! Просто используйте отметку времени в BSON: ObjectId

Получить продажи за последние 30 дней.

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

Поскольку поле id является индексным, вполне возможно, что это самый быстрый запрос.

Нужен диапазон дат? Cake.

Получить продажи с прошлого месяца.

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 ...

0 голосов
/ 15 октября 2011

Вы можете достичь этого, например, выполнив вызов 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 } } })

Это может сработать.

...