158 lines
3.4 KiB
Go
158 lines
3.4 KiB
Go
package models
|
|
|
|
import "git.kirsle.net/apps/gosocial/pkg/log"
|
|
|
|
// ForumStatistics queries for forum-level statistics.
|
|
type ForumStatistics struct {
|
|
RecentThread *Thread
|
|
Threads uint64
|
|
Posts uint64
|
|
Users uint64
|
|
}
|
|
|
|
type ForumStatsMap map[uint64]*ForumStatistics
|
|
|
|
// MapForumStatistics looks up statistics for a set of forums.
|
|
func MapForumStatistics(forums []*Forum) ForumStatsMap {
|
|
var (
|
|
result = ForumStatsMap{}
|
|
IDs = []uint64{}
|
|
)
|
|
|
|
// Collect forum IDs and initialize the map.
|
|
for _, forum := range forums {
|
|
IDs = append(IDs, forum.ID)
|
|
result[forum.ID] = &ForumStatistics{}
|
|
}
|
|
|
|
// FIRST: count the threads in each forum.
|
|
{
|
|
// Hold the result of the count/group by query.
|
|
type group struct {
|
|
ID uint64
|
|
Threads uint64
|
|
}
|
|
var groups = []group{}
|
|
|
|
// Count comments grouped by thread IDs.
|
|
err := DB.Table(
|
|
"threads",
|
|
).Select(
|
|
"forum_id AS id, count(id) AS threads",
|
|
).Where(
|
|
"forum_id IN ?",
|
|
IDs,
|
|
).Group("forum_id").Scan(&groups)
|
|
|
|
if err.Error != nil {
|
|
log.Error("MapForumStatistics: SQL error: %s", err.Error)
|
|
}
|
|
|
|
// Map the results in.
|
|
for _, row := range groups {
|
|
log.Error("Got row: %+v", row)
|
|
if stats, ok := result[row.ID]; ok {
|
|
stats.Threads = row.Threads
|
|
}
|
|
}
|
|
}
|
|
|
|
// THEN: count all posts in all those threads.
|
|
{
|
|
type group struct {
|
|
ID uint64
|
|
Posts uint64
|
|
}
|
|
var groups = []group{}
|
|
|
|
err := DB.Table(
|
|
"comments",
|
|
).Joins(
|
|
"JOIN threads ON (table_name = 'threads' AND table_id = threads.id)",
|
|
).Joins(
|
|
"JOIN forums ON (threads.forum_id = forums.id)",
|
|
).Select(
|
|
"forums.id AS id, count(comments.id) AS posts",
|
|
).Where(
|
|
`table_name = 'threads' AND EXISTS (
|
|
SELECT 1
|
|
FROM threads
|
|
WHERE table_id = threads.id
|
|
AND threads.forum_id IN ?
|
|
)`,
|
|
IDs,
|
|
).Group("forums.id").Scan(&groups)
|
|
|
|
if err.Error != nil {
|
|
log.Error("SQL error collecting posts for forum: %s", err.Error)
|
|
}
|
|
|
|
// Map the results in.
|
|
for _, row := range groups {
|
|
log.Error("Got row2: %+v", row)
|
|
if stats, ok := result[row.ID]; ok {
|
|
stats.Posts = row.Posts
|
|
}
|
|
}
|
|
}
|
|
|
|
// THEN: count all distinct users in those threads.
|
|
// TODO: hairy
|
|
// {
|
|
// type group struct {
|
|
// ID uint64
|
|
// Users uint64
|
|
// }
|
|
// var groups = []group{}
|
|
|
|
// err := DB.Table(
|
|
// "comments",
|
|
// ).Joins(
|
|
// "JOIN threads ON (table_name = 'threads' AND table_id = threads.id)",
|
|
// ).Joins(
|
|
// "JOIN forums ON (threads.forum_id = forums.id)",
|
|
// ).Select(
|
|
// "forums.id AS forum_id, count(distinct(comments.user_id)) AS users",
|
|
// ).Where(
|
|
// // `table_name = 'threads' AND EXISTS (
|
|
// // SELECT 1
|
|
// // FROM threads
|
|
// // WHERE table_id = threads.id
|
|
// // AND threads.forum_id IN ?
|
|
// // )`,
|
|
// "forums.id IN ?",
|
|
// IDs,
|
|
// ).Group("forums.id").Scan(&groups)
|
|
|
|
// if err.Error != nil {
|
|
// log.Error("SQL error collecting users for forum: %s", err.Error)
|
|
// }
|
|
|
|
// // Map the results in.
|
|
// for _, row := range groups {
|
|
// log.Error("Got row2: %+v", row)
|
|
// if stats, ok := result[row.ID]; ok {
|
|
// stats.Users = row.Users
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// Get THE most recent thread on this forum.
|
|
|
|
return result
|
|
}
|
|
|
|
// Has stats for this thread? (we should..)
|
|
func (ts ForumStatsMap) Has(threadID uint64) bool {
|
|
_, ok := ts[threadID]
|
|
return ok
|
|
}
|
|
|
|
// Get thread stats.
|
|
func (ts ForumStatsMap) Get(threadID uint64) *ForumStatistics {
|
|
if stats, ok := ts[threadID]; ok {
|
|
return stats
|
|
}
|
|
return nil
|
|
}
|