This repository has been archived on 2025-03-01. You can view files and clone it, but cannot push or open issues or pull requests.
trantor/database/stats.go

231 lines
5.1 KiB
Go
Raw Normal View History

2014-06-29 19:41:29 -05:00
package database
2013-06-01 02:34:11 +02:00
import (
2014-08-18 19:27:53 -05:00
"gopkg.in/mgo.v2"
"gopkg.in/mgo.v2/bson"
2013-06-01 02:34:11 +02:00
"time"
)
2014-06-29 19:41:29 -05:00
const (
stats_coll = "statistics"
hourly_visits_coll = "visits.hourly"
daily_visits_coll = "visits.daily"
monthly_visits_coll = "visits.monthly"
hourly_downloads_coll = "downloads.hourly"
daily_downloads_coll = "downloads.daily"
monthly_downloads_coll = "downloads.monthly"
// FIXME: this should return to the config.go
TAGS_DISPLAY = 50
BOOKS_FRONT_PAGE = 6
)
type dbUpdate struct {
2014-02-18 22:16:38 +01:00
src *mgo.Collection
dst *mgo.Collection
}
2014-06-29 19:41:29 -05:00
type VisitType int
const (
Hourly_visits = iota
Daily_visits
Monthly_visits
Hourly_downloads
Daily_downloads
Monthly_downloads
)
type Visits struct {
Date time.Time "date"
Count int "count"
}
2014-02-18 22:16:38 +01:00
func GetTags(tagsColl *mgo.Collection) ([]string, error) {
2013-06-01 02:34:11 +02:00
var result []struct {
Tag string "_id"
}
2014-02-18 22:16:38 +01:00
err := tagsColl.Find(nil).Sort("-count").All(&result)
2013-06-01 02:34:11 +02:00
if err != nil {
return nil, err
}
tags := make([]string, len(result))
for i, r := range result {
tags[i] = r.Tag
}
return tags, nil
}
2014-02-18 22:16:38 +01:00
func GetBooksVisited(visitedColl *mgo.Collection) ([]bson.ObjectId, error) {
var result []struct {
Book bson.ObjectId "_id"
}
2014-02-18 22:16:38 +01:00
err := visitedColl.Find(nil).Sort("-count").All(&result)
if err != nil {
return nil, err
}
books := make([]bson.ObjectId, len(result))
for i, r := range result {
books[i] = r.Book
}
return books, nil
}
func GetVisits(visitsColl *mgo.Collection) ([]Visits, error) {
var result []Visits
err := visitsColl.Find(nil).All(&result)
return result, err
}
2014-06-29 19:41:29 -05:00
func (u *dbUpdate) UpdateTags() error {
2014-02-18 21:35:26 +01:00
var tags []struct {
Tag string "_id"
Count int "count"
}
2014-02-18 22:16:38 +01:00
err := u.src.Pipe([]bson.M{
2014-02-18 21:35:26 +01:00
{"$project": bson.M{"subject": 1}},
{"$unwind": "$subject"},
{"$group": bson.M{"_id": "$subject", "count": bson.M{"$sum": 1}}},
{"$sort": bson.M{"count": -1}},
{"$limit": TAGS_DISPLAY},
}).All(&tags)
if err != nil {
return err
}
2014-02-18 22:16:38 +01:00
u.dst.DropCollection()
2014-02-18 21:35:26 +01:00
for _, tag := range tags {
2014-02-18 22:16:38 +01:00
err = u.dst.Insert(tag)
2014-02-18 21:35:26 +01:00
if err != nil {
return err
}
}
return nil
2013-06-01 03:40:06 +02:00
}
2014-06-29 19:41:29 -05:00
func (u *dbUpdate) UpdateMostBooks(section string) error {
const numDays = 30
start := time.Now().UTC().Add(-numDays * 24 * time.Hour)
2014-02-18 21:50:44 +01:00
var books []struct {
Book string "_id"
Count int "count"
}
2014-02-18 22:16:38 +01:00
err := u.src.Pipe([]bson.M{
2014-02-18 21:50:44 +01:00
{"$match": bson.M{"date": bson.M{"$gt": start}, "section": section}},
{"$project": bson.M{"id": 1}},
{"$group": bson.M{"_id": "$id", "count": bson.M{"$sum": 1}}},
{"$sort": bson.M{"count": -1}},
{"$limit": BOOKS_FRONT_PAGE},
}).All(&books)
if err != nil {
return err
}
2014-02-18 22:16:38 +01:00
u.dst.DropCollection()
2014-02-18 21:50:44 +01:00
for _, book := range books {
2014-02-18 22:16:38 +01:00
err = u.dst.Insert(book)
2014-02-18 21:50:44 +01:00
if err != nil {
return err
}
}
return nil
2013-06-01 02:34:11 +02:00
}
2014-06-29 19:41:29 -05:00
func (u *dbUpdate) UpdateHourVisits(isDownloads bool) error {
const numDays = 2
spanStore := numDays * 24 * time.Hour
2014-02-19 01:20:10 +01:00
return u.updateVisits(hourInc, spanStore, isDownloads)
}
2013-06-01 03:40:06 +02:00
2014-06-29 19:41:29 -05:00
func (u *dbUpdate) UpdateDayVisits(isDownloads bool) error {
const numDays = 30
spanStore := numDays * 24 * time.Hour
2014-02-19 01:20:10 +01:00
return u.updateVisits(dayInc, spanStore, isDownloads)
2013-06-01 03:40:06 +02:00
}
2014-06-29 19:41:29 -05:00
func (u *dbUpdate) UpdateMonthVisits(isDownloads bool) error {
const numDays = 365
spanStore := numDays * 24 * time.Hour
2014-02-19 01:20:10 +01:00
return u.updateVisits(monthInc, spanStore, isDownloads)
}
2014-02-19 01:20:10 +01:00
func hourInc(date time.Time) time.Time {
const span = time.Hour
return date.Add(span).Truncate(span)
}
2014-02-19 01:20:10 +01:00
func dayInc(date time.Time) time.Time {
const span = 24 * time.Hour
return date.Add(span).Truncate(span)
}
2014-02-19 01:20:10 +01:00
func monthInc(date time.Time) time.Time {
const span = 24 * time.Hour
return date.AddDate(0, 1, 1-date.Day()).Truncate(span)
}
2014-06-29 19:41:29 -05:00
func (u *dbUpdate) updateVisits(incTime func(time.Time) time.Time, spanStore time.Duration, isDownloads bool) error {
2014-02-18 22:16:38 +01:00
start := u.calculateStart(spanStore)
for start.Before(time.Now().UTC()) {
stop := incTime(start)
var count int
var err error
2014-02-19 01:20:10 +01:00
if isDownloads {
2014-02-18 22:16:38 +01:00
count, err = u.countDownloads(start, stop)
2014-02-19 01:20:10 +01:00
} else {
count = u.countVisits(start, stop)
}
if err != nil {
return err
}
2014-02-18 22:16:38 +01:00
err = u.dst.Insert(bson.M{"date": start, "count": count})
if err != nil {
return err
}
start = stop
}
2014-02-18 22:16:38 +01:00
_, err := u.dst.RemoveAll(bson.M{"date": bson.M{"$lt": time.Now().UTC().Add(-spanStore)}})
return err
}
2014-06-29 19:41:29 -05:00
func (u *dbUpdate) calculateStart(spanStore time.Duration) time.Time {
var date struct {
Id bson.ObjectId `bson:"_id"`
Date time.Time `bson:"date"`
}
2014-02-18 22:16:38 +01:00
err := u.dst.Find(bson.M{}).Sort("-date").One(&date)
if err == nil {
2014-02-18 22:16:38 +01:00
u.dst.RemoveId(date.Id)
return date.Date
}
return time.Now().UTC().Add(-spanStore).Truncate(time.Hour)
}
2014-06-29 19:41:29 -05:00
func (u *dbUpdate) countVisits(start time.Time, stop time.Time) int {
var result struct {
Count int "count"
}
2014-02-18 22:16:38 +01:00
err := u.src.Pipe([]bson.M{
{"$match": bson.M{"date": bson.M{"$gte": start, "$lt": stop}}},
{"$group": bson.M{"_id": "$session"}},
{"$group": bson.M{"_id": 1, "count": bson.M{"$sum": 1}}},
}).One(&result)
if err != nil {
return 0
}
return result.Count
}
2014-06-29 19:41:29 -05:00
func (u *dbUpdate) countDownloads(start time.Time, stop time.Time) (int, error) {
query := bson.M{"date": bson.M{"$gte": start, "$lt": stop}, "section": "download"}
2014-02-18 22:16:38 +01:00
return u.src.Find(query).Count()
2013-06-01 02:34:11 +02:00
}