-
Notifications
You must be signed in to change notification settings - Fork 6
/
article_filter.go
119 lines (95 loc) · 2.53 KB
/
article_filter.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
package blog
import (
"github.com/go-pg/urlstruct"
"github.com/uptrace/bun"
"github.com/uptrace/bun-realworld-app/bunapp"
"github.com/uptrace/bun-realworld-app/org"
"github.com/uptrace/bunrouter"
)
type ArticleFilter struct {
app *bunapp.App
UserID uint64
Author string
Tag string
Favorited string
Slug string
Feed bool
urlstruct.Pager
}
func decodeArticleFilter(app *bunapp.App, req bunrouter.Request) (*ArticleFilter, error) {
ctx := req.Context()
query := req.URL.Query()
f := &ArticleFilter{
app: app,
Tag: query.Get("tag"),
Author: query.Get("author"),
Favorited: query.Get("favorited"),
Slug: req.Param("slug"),
}
if user := org.UserFromContext(ctx); user != nil {
f.UserID = user.ID
}
return f, nil
}
func (f *ArticleFilter) query(q *bun.SelectQuery) *bun.SelectQuery {
q = q.Relation("Author")
{
subq := f.app.DB().NewSelect().
Model((*ArticleTag)(nil)).
ColumnExpr("array_agg(t.tag)::text[]").
Where("t.article_id = a.id")
q = q.ColumnExpr("(?) AS tag_list", subq)
}
if f.UserID == 0 {
q = q.ColumnExpr("false AS favorited")
} else {
subq := f.app.DB().NewSelect().
Model((*FavoriteArticle)(nil)).
Where("fa.article_id = a.id").
Where("fa.user_id = ?", f.UserID)
q = q.ColumnExpr("EXISTS (?) AS favorited", subq)
}
q.Apply(authorFollowingColumn(f.app, f.UserID))
{
subq := f.app.DB().NewSelect().
Model((*FavoriteArticle)(nil)).
ColumnExpr("count(*)").
Where("fa.article_id = a.id")
q = q.ColumnExpr("(?) AS favorites_count", subq)
}
if f.Author != "" {
q = q.Where("author.username = ?", f.Author)
}
if f.Tag != "" {
subq := f.app.DB().NewSelect().
Model((*ArticleTag)(nil)).
Distinct().
ColumnExpr("t.article_id").
Where("t.tag = ?", f.Tag)
q = q.Where("a.id IN (?)", subq)
}
if f.Feed {
subq := f.app.DB().NewSelect().
Model((*org.FollowUser)(nil)).
ColumnExpr("fu.followed_user_id").
Where("fu.user_id = ?", f.UserID)
q = q.Where("a.author_id IN (?)", subq)
} else if f.Slug != "" {
q = q.Where("a.slug = ?", f.Slug)
}
return q
}
func authorFollowingColumn(app *bunapp.App, userID uint64) func(*bun.SelectQuery) *bun.SelectQuery {
return func(q *bun.SelectQuery) *bun.SelectQuery {
if userID == 0 {
q = q.ColumnExpr("false AS author__following")
} else {
subq := app.DB().NewSelect().
Model((*org.FollowUser)(nil)).
Where("fu.followed_user_id = author_id").
Where("fu.user_id = ?", userID)
q = q.ColumnExpr("EXISTS (?) AS author__following", subq)
}
return q
}
}