2019-05-02 17:17:27 -05:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2013-02-05 13:16:51 -06:00
|
|
|
class UserVisit < ActiveRecord::Base
|
2016-02-02 20:29:51 -06:00
|
|
|
def self.counts_by_day_query(start_date, end_date, group_id = nil)
|
|
|
|
result = where('visited_at >= ? and visited_at <= ?', start_date.to_date, end_date.to_date)
|
|
|
|
|
|
|
|
if group_id
|
|
|
|
result = result.joins("INNER JOIN users ON users.id = user_visits.user_id")
|
|
|
|
result = result.joins("INNER JOIN group_users ON group_users.user_id = users.id")
|
|
|
|
result = result.where("group_users.group_id = ?", group_id)
|
|
|
|
end
|
|
|
|
result.group(:visited_at).order(:visited_at)
|
2015-07-07 11:31:07 -05:00
|
|
|
end
|
|
|
|
|
2018-05-03 08:41:41 -05:00
|
|
|
def self.count_by_active_users(start_date, end_date)
|
2018-06-19 01:13:14 -05:00
|
|
|
sql = <<~SQL
|
2018-05-03 08:41:41 -05:00
|
|
|
WITH dau AS (
|
2018-05-10 22:30:21 -05:00
|
|
|
SELECT date_trunc('day', user_visits.visited_at)::DATE AS date,
|
2018-05-03 08:41:41 -05:00
|
|
|
count(distinct user_visits.user_id) AS dau
|
|
|
|
FROM user_visits
|
2018-05-11 00:06:09 -05:00
|
|
|
WHERE user_visits.visited_at::DATE >= :start_date::DATE AND user_visits.visited_at <= :end_date::DATE
|
2018-05-10 22:30:21 -05:00
|
|
|
GROUP BY date_trunc('day', user_visits.visited_at)::DATE
|
|
|
|
ORDER BY date_trunc('day', user_visits.visited_at)::DATE
|
2018-05-03 08:41:41 -05:00
|
|
|
)
|
|
|
|
|
|
|
|
SELECT date, dau,
|
|
|
|
(SELECT count(distinct user_visits.user_id)
|
|
|
|
FROM user_visits
|
|
|
|
WHERE user_visits.visited_at::DATE BETWEEN dau.date - 29 AND dau.date
|
|
|
|
) AS mau
|
|
|
|
FROM dau
|
2018-06-19 01:13:14 -05:00
|
|
|
SQL
|
2018-05-03 08:41:41 -05:00
|
|
|
|
2018-06-19 01:13:14 -05:00
|
|
|
DB.query_hash(sql, start_date: start_date, end_date: end_date)
|
2018-05-03 08:41:41 -05:00
|
|
|
end
|
|
|
|
|
2015-07-07 11:31:07 -05:00
|
|
|
# A count of visits in a date range by day
|
2016-02-02 20:29:51 -06:00
|
|
|
def self.by_day(start_date, end_date, group_id = nil)
|
|
|
|
counts_by_day_query(start_date, end_date, group_id).count
|
2015-07-07 11:31:07 -05:00
|
|
|
end
|
|
|
|
|
2016-02-02 20:29:51 -06:00
|
|
|
def self.mobile_by_day(start_date, end_date, group_id = nil)
|
|
|
|
counts_by_day_query(start_date, end_date, group_id).where(mobile: true).count
|
2013-02-27 21:39:42 -06:00
|
|
|
end
|
2013-04-05 01:43:48 -05:00
|
|
|
|
|
|
|
def self.ensure_consistency!
|
2018-06-19 01:13:14 -05:00
|
|
|
DB.exec <<~SQL
|
|
|
|
UPDATE user_stats u set days_visited =
|
|
|
|
(
|
|
|
|
SELECT COUNT(*) FROM user_visits v WHERE v.user_id = u.user_id
|
|
|
|
)
|
|
|
|
WHERE days_visited <>
|
|
|
|
(
|
|
|
|
SELECT COUNT(*) FROM user_visits v WHERE v.user_id = u.user_id
|
|
|
|
)
|
|
|
|
SQL
|
2013-04-05 01:43:48 -05:00
|
|
|
end
|
2013-02-05 13:16:51 -06:00
|
|
|
end
|
2013-05-23 21:48:32 -05:00
|
|
|
|
|
|
|
# == Schema Information
|
|
|
|
#
|
|
|
|
# Table name: user_visits
|
|
|
|
#
|
|
|
|
# id :integer not null, primary key
|
|
|
|
# user_id :integer not null
|
|
|
|
# visited_at :date not null
|
2014-02-06 18:07:36 -06:00
|
|
|
# posts_read :integer default(0)
|
2015-07-07 11:31:07 -05:00
|
|
|
# mobile :boolean default(FALSE)
|
2017-11-23 14:55:44 -06:00
|
|
|
# time_read :integer default(0), not null
|
2013-05-23 21:48:32 -05:00
|
|
|
#
|
|
|
|
# Indexes
|
|
|
|
#
|
2017-11-23 14:55:44 -06:00
|
|
|
# index_user_visits_on_user_id_and_visited_at (user_id,visited_at) UNIQUE
|
|
|
|
# index_user_visits_on_user_id_and_visited_at_and_time_read (user_id,visited_at,time_read)
|
|
|
|
# index_user_visits_on_visited_at_and_mobile (visited_at,mobile)
|
2013-05-23 21:48:32 -05:00
|
|
|
#
|