nandi/gleanpublic Fork 0
73f96db
Commits
Clone
git clone https://git.rickub.com/nandi/glean.git
git clone ssh://git@rickub.com/nandi/glean.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

Use correlated subqueries for likes in article queries and add indexesUnverified

Julien Robert committed 2026-05-07T22:46:32+02:00 Browse files
73f96db parent: 8e6871d
modified internal/db/article.go +12 -36
@@ -115,15 +115,11 @@ func (s *ArticleStore) ListArticles(ctx context.Context, userDID, feedURL string
115115 SELECT a.id, a.feed_url, COALESCE(f.title, ''), f.favicon_url, a.guid, a.title, a.url, a.author, a.summary, a.content,
116116 a.published, a.updated, a.fetched_at,
117117 COALESCE(r.is_read, 0),
118- COALESCE(lc.cnt, 0),
119- COALESCE(ul.liked, 0)
118+ (SELECT COUNT(*) FROM articles.likes l2 WHERE l2.feed_url = a.feed_url AND l2.article_url = a.url),
119+ COALESCE((SELECT 1 FROM articles.likes l3 WHERE l3.feed_url = a.feed_url AND l3.article_url = a.url AND l3.author_did = ?), 0)
120120 FROM articles.articles a
121121 LEFT JOIN articles.feeds f ON a.feed_url = f.feed_url
122122 LEFT JOIN articles.read_state r ON r.user_did = ? AND r.article_id = a.id
123- LEFT JOIN (SELECT feed_url, article_url, COUNT(*) as cnt FROM articles.likes GROUP BY feed_url, article_url) lc
124- ON lc.feed_url = a.feed_url AND lc.article_url = a.url
125- LEFT JOIN (SELECT feed_url, article_url, 1 as liked FROM articles.likes WHERE author_did = ?) ul
126- ON ul.feed_url = a.feed_url AND ul.article_url = a.url
127123 WHERE a.feed_url = ?
128124 `
129125 args = []any{userDID, userDID, feedURL}
@@ -132,16 +128,12 @@ func (s *ArticleStore) ListArticles(ctx context.Context, userDID, feedURL string
132128 SELECT a.id, a.feed_url, COALESCE(f.title, ''), f.favicon_url, a.guid, a.title, a.url, a.author, a.summary, a.content,
133129 a.published, a.updated, a.fetched_at,
134130 COALESCE(r.is_read, 0),
135- COALESCE(lc.cnt, 0),
136- COALESCE(ul.liked, 0)
131+ (SELECT COUNT(*) FROM articles.likes l2 WHERE l2.feed_url = a.feed_url AND l2.article_url = a.url),
132+ COALESCE((SELECT 1 FROM articles.likes l3 WHERE l3.feed_url = a.feed_url AND l3.article_url = a.url AND l3.author_did = ?), 0)
137133 FROM articles.articles a
138134 JOIN articles.subscriptions s ON a.feed_url = s.feed_url AND s.user_did = ?
139135 LEFT JOIN articles.feeds f ON a.feed_url = f.feed_url
140136 LEFT JOIN articles.read_state r ON r.user_did = ? AND r.article_id = a.id
141- LEFT JOIN (SELECT feed_url, article_url, COUNT(*) as cnt FROM articles.likes GROUP BY feed_url, article_url) lc
142- ON lc.feed_url = a.feed_url AND lc.article_url = a.url
143- LEFT JOIN (SELECT feed_url, article_url, 1 as liked FROM articles.likes WHERE author_did = ?) ul
144- ON ul.feed_url = a.feed_url AND ul.article_url = a.url
145137 WHERE 1=1
146138 `
147139 args = []any{userDID, userDID, userDID}
@@ -179,15 +171,11 @@ func (s *ArticleStore) ListUnreadArticles(ctx context.Context, userDID, feedURL
179171 SELECT a.id, a.feed_url, COALESCE(f.title, ''), f.favicon_url, a.guid, a.title, a.url, a.author, a.summary, a.content,
180172 a.published, a.updated, a.fetched_at,
181173 COALESCE(r.is_read, 0),
182- COALESCE(lc.cnt, 0),
183- COALESCE(ul.liked, 0)
174+ (SELECT COUNT(*) FROM articles.likes l2 WHERE l2.feed_url = a.feed_url AND l2.article_url = a.url),
175+ COALESCE((SELECT 1 FROM articles.likes l3 WHERE l3.feed_url = a.feed_url AND l3.article_url = a.url AND l3.author_did = ?), 0)
184176 FROM articles.articles a
185177 LEFT JOIN articles.feeds f ON a.feed_url = f.feed_url
186178 LEFT JOIN articles.read_state r ON r.user_did = ? AND r.article_id = a.id
187- LEFT JOIN (SELECT feed_url, article_url, COUNT(*) as cnt FROM articles.likes GROUP BY feed_url, article_url) lc
188- ON lc.feed_url = a.feed_url AND lc.article_url = a.url
189- LEFT JOIN (SELECT feed_url, article_url, 1 as liked FROM articles.likes WHERE author_did = ?) ul
190- ON ul.feed_url = a.feed_url AND ul.article_url = a.url
191179 WHERE a.feed_url = ? AND (r.is_read = 0 OR r.is_read IS NULL)
192180 `
193181 args = []any{userDID, userDID, feedURL}
@@ -196,16 +184,12 @@ func (s *ArticleStore) ListUnreadArticles(ctx context.Context, userDID, feedURL
196184 SELECT a.id, a.feed_url, COALESCE(f.title, ''), f.favicon_url, a.guid, a.title, a.url, a.author, a.summary, a.content,
197185 a.published, a.updated, a.fetched_at,
198186 COALESCE(r.is_read, 0),
199- COALESCE(lc.cnt, 0),
200- COALESCE(ul.liked, 0)
187+ (SELECT COUNT(*) FROM articles.likes l2 WHERE l2.feed_url = a.feed_url AND l2.article_url = a.url),
188+ COALESCE((SELECT 1 FROM articles.likes l3 WHERE l3.feed_url = a.feed_url AND l3.article_url = a.url AND l3.author_did = ?), 0)
201189 FROM articles.articles a
202190 JOIN articles.subscriptions s ON a.feed_url = s.feed_url AND s.user_did = ?
203191 LEFT JOIN articles.feeds f ON a.feed_url = f.feed_url
204192 LEFT JOIN articles.read_state r ON r.user_did = ? AND r.article_id = a.id
205- LEFT JOIN (SELECT feed_url, article_url, COUNT(*) as cnt FROM articles.likes GROUP BY feed_url, article_url) lc
206- ON lc.feed_url = a.feed_url AND lc.article_url = a.url
207- LEFT JOIN (SELECT feed_url, article_url, 1 as liked FROM articles.likes WHERE author_did = ?) ul
208- ON ul.feed_url = a.feed_url AND ul.article_url = a.url
209193 WHERE (r.is_read = 0 OR r.is_read IS NULL)
210194 `
211195 args = []any{userDID, userDID, userDID}
@@ -243,15 +227,11 @@ func (s *ArticleStore) ListReadArticles(ctx context.Context, userDID, feedURL st
243227 SELECT a.id, a.feed_url, COALESCE(f.title, ''), f.favicon_url, a.guid, a.title, a.url, a.author, a.summary, a.content,
244228 a.published, a.updated, a.fetched_at,
245229 COALESCE(r.is_read, 0),
246- COALESCE(lc.cnt, 0),
247- COALESCE(ul.liked, 0)
230+ (SELECT COUNT(*) FROM articles.likes l2 WHERE l2.feed_url = a.feed_url AND l2.article_url = a.url),
231+ COALESCE((SELECT 1 FROM articles.likes l3 WHERE l3.feed_url = a.feed_url AND l3.article_url = a.url AND l3.author_did = ?), 0)
248232 FROM articles.articles a
249233 LEFT JOIN articles.feeds f ON a.feed_url = f.feed_url
250234 JOIN articles.read_state r ON r.user_did = ? AND r.article_id = a.id
251- LEFT JOIN (SELECT feed_url, article_url, COUNT(*) as cnt FROM articles.likes GROUP BY feed_url, article_url) lc
252- ON lc.feed_url = a.feed_url AND lc.article_url = a.url
253- LEFT JOIN (SELECT feed_url, article_url, 1 as liked FROM articles.likes WHERE author_did = ?) ul
254- ON ul.feed_url = a.feed_url AND ul.article_url = a.url
255235 WHERE r.is_read = 1 AND a.feed_url = ?
256236 `
257237 args = []any{userDID, userDID, feedURL}
@@ -260,16 +240,12 @@ func (s *ArticleStore) ListReadArticles(ctx context.Context, userDID, feedURL st
260240 SELECT a.id, a.feed_url, COALESCE(f.title, ''), f.favicon_url, a.guid, a.title, a.url, a.author, a.summary, a.content,
261241 a.published, a.updated, a.fetched_at,
262242 COALESCE(r.is_read, 0),
263- COALESCE(lc.cnt, 0),
264- COALESCE(ul.liked, 0)
243+ (SELECT COUNT(*) FROM articles.likes l2 WHERE l2.feed_url = a.feed_url AND l2.article_url = a.url),
244+ COALESCE((SELECT 1 FROM articles.likes l3 WHERE l3.feed_url = a.feed_url AND l3.article_url = a.url AND l3.author_did = ?), 0)
265245 FROM articles.articles a
266246 JOIN articles.subscriptions s ON a.feed_url = s.feed_url AND s.user_did = ?
267247 LEFT JOIN articles.feeds f ON a.feed_url = f.feed_url
268248 JOIN articles.read_state r ON r.user_did = ? AND r.article_id = a.id
269- LEFT JOIN (SELECT feed_url, article_url, COUNT(*) as cnt FROM articles.likes GROUP BY feed_url, article_url) lc
270- ON lc.feed_url = a.feed_url AND lc.article_url = a.url
271- LEFT JOIN (SELECT feed_url, article_url, 1 as liked FROM articles.likes WHERE author_did = ?) ul
272- ON ul.feed_url = a.feed_url AND ul.article_url = a.url
273249 WHERE r.is_read = 1
274250 `
275251 args = []any{userDID, userDID, userDID}
@@ -115,15 +115,11 @@ func (s *ArticleStore) ListArticles(ctx context.Context, userDID, feedURL string
115 SELECT a.id, a.feed_url, COALESCE(f.title, ''), f.favicon_url, a.guid, a.title, a.url, a.author, a.summary, a.content,115 SELECT a.id, a.feed_url, COALESCE(f.title, ''), f.favicon_url, a.guid, a.title, a.url, a.author, a.summary, a.content,
116 a.published, a.updated, a.fetched_at,116 a.published, a.updated, a.fetched_at,
117 COALESCE(r.is_read, 0),117 COALESCE(r.is_read, 0),
118- COALESCE(lc.cnt, 0),118+ (SELECT COUNT(*) FROM articles.likes l2 WHERE l2.feed_url = a.feed_url AND l2.article_url = a.url),
119- COALESCE(ul.liked, 0)119+ COALESCE((SELECT 1 FROM articles.likes l3 WHERE l3.feed_url = a.feed_url AND l3.article_url = a.url AND l3.author_did = ?), 0)
120 FROM articles.articles a120 FROM articles.articles a
121 LEFT JOIN articles.feeds f ON a.feed_url = f.feed_url121 LEFT JOIN articles.feeds f ON a.feed_url = f.feed_url
122 LEFT JOIN articles.read_state r ON r.user_did = ? AND r.article_id = a.id122 LEFT JOIN articles.read_state r ON r.user_did = ? AND r.article_id = a.id
123- LEFT JOIN (SELECT feed_url, article_url, COUNT(*) as cnt FROM articles.likes GROUP BY feed_url, article_url) lc
124- ON lc.feed_url = a.feed_url AND lc.article_url = a.url
125- LEFT JOIN (SELECT feed_url, article_url, 1 as liked FROM articles.likes WHERE author_did = ?) ul
126- ON ul.feed_url = a.feed_url AND ul.article_url = a.url
127 WHERE a.feed_url = ?123 WHERE a.feed_url = ?
128 `124 `
129 args = []any{userDID, userDID, feedURL}125 args = []any{userDID, userDID, feedURL}
@@ -132,16 +128,12 @@ func (s *ArticleStore) ListArticles(ctx context.Context, userDID, feedURL string
132 SELECT a.id, a.feed_url, COALESCE(f.title, ''), f.favicon_url, a.guid, a.title, a.url, a.author, a.summary, a.content,128 SELECT a.id, a.feed_url, COALESCE(f.title, ''), f.favicon_url, a.guid, a.title, a.url, a.author, a.summary, a.content,
133 a.published, a.updated, a.fetched_at,129 a.published, a.updated, a.fetched_at,
134 COALESCE(r.is_read, 0),130 COALESCE(r.is_read, 0),
135- COALESCE(lc.cnt, 0),131+ (SELECT COUNT(*) FROM articles.likes l2 WHERE l2.feed_url = a.feed_url AND l2.article_url = a.url),
136- COALESCE(ul.liked, 0)132+ COALESCE((SELECT 1 FROM articles.likes l3 WHERE l3.feed_url = a.feed_url AND l3.article_url = a.url AND l3.author_did = ?), 0)
137 FROM articles.articles a133 FROM articles.articles a
138 JOIN articles.subscriptions s ON a.feed_url = s.feed_url AND s.user_did = ?134 JOIN articles.subscriptions s ON a.feed_url = s.feed_url AND s.user_did = ?
139 LEFT JOIN articles.feeds f ON a.feed_url = f.feed_url135 LEFT JOIN articles.feeds f ON a.feed_url = f.feed_url
140 LEFT JOIN articles.read_state r ON r.user_did = ? AND r.article_id = a.id136 LEFT JOIN articles.read_state r ON r.user_did = ? AND r.article_id = a.id
141- LEFT JOIN (SELECT feed_url, article_url, COUNT(*) as cnt FROM articles.likes GROUP BY feed_url, article_url) lc
142- ON lc.feed_url = a.feed_url AND lc.article_url = a.url
143- LEFT JOIN (SELECT feed_url, article_url, 1 as liked FROM articles.likes WHERE author_did = ?) ul
144- ON ul.feed_url = a.feed_url AND ul.article_url = a.url
145 WHERE 1=1137 WHERE 1=1
146 `138 `
147 args = []any{userDID, userDID, userDID}139 args = []any{userDID, userDID, userDID}
@@ -179,15 +171,11 @@ func (s *ArticleStore) ListUnreadArticles(ctx context.Context, userDID, feedURL
179 SELECT a.id, a.feed_url, COALESCE(f.title, ''), f.favicon_url, a.guid, a.title, a.url, a.author, a.summary, a.content,171 SELECT a.id, a.feed_url, COALESCE(f.title, ''), f.favicon_url, a.guid, a.title, a.url, a.author, a.summary, a.content,
180 a.published, a.updated, a.fetched_at,172 a.published, a.updated, a.fetched_at,
181 COALESCE(r.is_read, 0),173 COALESCE(r.is_read, 0),
182- COALESCE(lc.cnt, 0),174+ (SELECT COUNT(*) FROM articles.likes l2 WHERE l2.feed_url = a.feed_url AND l2.article_url = a.url),
183- COALESCE(ul.liked, 0)175+ COALESCE((SELECT 1 FROM articles.likes l3 WHERE l3.feed_url = a.feed_url AND l3.article_url = a.url AND l3.author_did = ?), 0)
184 FROM articles.articles a176 FROM articles.articles a
185 LEFT JOIN articles.feeds f ON a.feed_url = f.feed_url177 LEFT JOIN articles.feeds f ON a.feed_url = f.feed_url
186 LEFT JOIN articles.read_state r ON r.user_did = ? AND r.article_id = a.id178 LEFT JOIN articles.read_state r ON r.user_did = ? AND r.article_id = a.id
187- LEFT JOIN (SELECT feed_url, article_url, COUNT(*) as cnt FROM articles.likes GROUP BY feed_url, article_url) lc
188- ON lc.feed_url = a.feed_url AND lc.article_url = a.url
189- LEFT JOIN (SELECT feed_url, article_url, 1 as liked FROM articles.likes WHERE author_did = ?) ul
190- ON ul.feed_url = a.feed_url AND ul.article_url = a.url
191 WHERE a.feed_url = ? AND (r.is_read = 0 OR r.is_read IS NULL)179 WHERE a.feed_url = ? AND (r.is_read = 0 OR r.is_read IS NULL)
192 `180 `
193 args = []any{userDID, userDID, feedURL}181 args = []any{userDID, userDID, feedURL}
@@ -196,16 +184,12 @@ func (s *ArticleStore) ListUnreadArticles(ctx context.Context, userDID, feedURL
196 SELECT a.id, a.feed_url, COALESCE(f.title, ''), f.favicon_url, a.guid, a.title, a.url, a.author, a.summary, a.content,184 SELECT a.id, a.feed_url, COALESCE(f.title, ''), f.favicon_url, a.guid, a.title, a.url, a.author, a.summary, a.content,
197 a.published, a.updated, a.fetched_at,185 a.published, a.updated, a.fetched_at,
198 COALESCE(r.is_read, 0),186 COALESCE(r.is_read, 0),
199- COALESCE(lc.cnt, 0),187+ (SELECT COUNT(*) FROM articles.likes l2 WHERE l2.feed_url = a.feed_url AND l2.article_url = a.url),
200- COALESCE(ul.liked, 0)188+ COALESCE((SELECT 1 FROM articles.likes l3 WHERE l3.feed_url = a.feed_url AND l3.article_url = a.url AND l3.author_did = ?), 0)
201 FROM articles.articles a189 FROM articles.articles a
202 JOIN articles.subscriptions s ON a.feed_url = s.feed_url AND s.user_did = ?190 JOIN articles.subscriptions s ON a.feed_url = s.feed_url AND s.user_did = ?
203 LEFT JOIN articles.feeds f ON a.feed_url = f.feed_url191 LEFT JOIN articles.feeds f ON a.feed_url = f.feed_url
204 LEFT JOIN articles.read_state r ON r.user_did = ? AND r.article_id = a.id192 LEFT JOIN articles.read_state r ON r.user_did = ? AND r.article_id = a.id
205- LEFT JOIN (SELECT feed_url, article_url, COUNT(*) as cnt FROM articles.likes GROUP BY feed_url, article_url) lc
206- ON lc.feed_url = a.feed_url AND lc.article_url = a.url
207- LEFT JOIN (SELECT feed_url, article_url, 1 as liked FROM articles.likes WHERE author_did = ?) ul
208- ON ul.feed_url = a.feed_url AND ul.article_url = a.url
209 WHERE (r.is_read = 0 OR r.is_read IS NULL)193 WHERE (r.is_read = 0 OR r.is_read IS NULL)
210 `194 `
211 args = []any{userDID, userDID, userDID}195 args = []any{userDID, userDID, userDID}
@@ -243,15 +227,11 @@ func (s *ArticleStore) ListReadArticles(ctx context.Context, userDID, feedURL st
243 SELECT a.id, a.feed_url, COALESCE(f.title, ''), f.favicon_url, a.guid, a.title, a.url, a.author, a.summary, a.content,227 SELECT a.id, a.feed_url, COALESCE(f.title, ''), f.favicon_url, a.guid, a.title, a.url, a.author, a.summary, a.content,
244 a.published, a.updated, a.fetched_at,228 a.published, a.updated, a.fetched_at,
245 COALESCE(r.is_read, 0),229 COALESCE(r.is_read, 0),
246- COALESCE(lc.cnt, 0),230+ (SELECT COUNT(*) FROM articles.likes l2 WHERE l2.feed_url = a.feed_url AND l2.article_url = a.url),
247- COALESCE(ul.liked, 0)231+ COALESCE((SELECT 1 FROM articles.likes l3 WHERE l3.feed_url = a.feed_url AND l3.article_url = a.url AND l3.author_did = ?), 0)
248 FROM articles.articles a232 FROM articles.articles a
249 LEFT JOIN articles.feeds f ON a.feed_url = f.feed_url233 LEFT JOIN articles.feeds f ON a.feed_url = f.feed_url
250 JOIN articles.read_state r ON r.user_did = ? AND r.article_id = a.id234 JOIN articles.read_state r ON r.user_did = ? AND r.article_id = a.id
251- LEFT JOIN (SELECT feed_url, article_url, COUNT(*) as cnt FROM articles.likes GROUP BY feed_url, article_url) lc
252- ON lc.feed_url = a.feed_url AND lc.article_url = a.url
253- LEFT JOIN (SELECT feed_url, article_url, 1 as liked FROM articles.likes WHERE author_did = ?) ul
254- ON ul.feed_url = a.feed_url AND ul.article_url = a.url
255 WHERE r.is_read = 1 AND a.feed_url = ?235 WHERE r.is_read = 1 AND a.feed_url = ?
256 `236 `
257 args = []any{userDID, userDID, feedURL}237 args = []any{userDID, userDID, feedURL}
@@ -260,16 +240,12 @@ func (s *ArticleStore) ListReadArticles(ctx context.Context, userDID, feedURL st
260 SELECT a.id, a.feed_url, COALESCE(f.title, ''), f.favicon_url, a.guid, a.title, a.url, a.author, a.summary, a.content,240 SELECT a.id, a.feed_url, COALESCE(f.title, ''), f.favicon_url, a.guid, a.title, a.url, a.author, a.summary, a.content,
261 a.published, a.updated, a.fetched_at,241 a.published, a.updated, a.fetched_at,
262 COALESCE(r.is_read, 0),242 COALESCE(r.is_read, 0),
263- COALESCE(lc.cnt, 0),243+ (SELECT COUNT(*) FROM articles.likes l2 WHERE l2.feed_url = a.feed_url AND l2.article_url = a.url),
264- COALESCE(ul.liked, 0)244+ COALESCE((SELECT 1 FROM articles.likes l3 WHERE l3.feed_url = a.feed_url AND l3.article_url = a.url AND l3.author_did = ?), 0)
265 FROM articles.articles a245 FROM articles.articles a
266 JOIN articles.subscriptions s ON a.feed_url = s.feed_url AND s.user_did = ?246 JOIN articles.subscriptions s ON a.feed_url = s.feed_url AND s.user_did = ?
267 LEFT JOIN articles.feeds f ON a.feed_url = f.feed_url247 LEFT JOIN articles.feeds f ON a.feed_url = f.feed_url
268 JOIN articles.read_state r ON r.user_did = ? AND r.article_id = a.id248 JOIN articles.read_state r ON r.user_did = ? AND r.article_id = a.id
269- LEFT JOIN (SELECT feed_url, article_url, COUNT(*) as cnt FROM articles.likes GROUP BY feed_url, article_url) lc
270- ON lc.feed_url = a.feed_url AND lc.article_url = a.url
271- LEFT JOIN (SELECT feed_url, article_url, 1 as liked FROM articles.likes WHERE author_did = ?) ul
272- ON ul.feed_url = a.feed_url AND ul.article_url = a.url
273 WHERE r.is_read = 1249 WHERE r.is_read = 1
274 `250 `
275 args = []any{userDID, userDID, userDID}251 args = []any{userDID, userDID, userDID}
modified internal/db/db.go +3 -0
@@ -370,6 +370,9 @@ var articlesSchema = []string{
370370 `CREATE INDEX IF NOT EXISTS articles.idx_likes_author ON likes(author_did)`,
371371 `CREATE INDEX IF NOT EXISTS articles.idx_likes_created_at ON likes(created_at DESC)`,
372372 `CREATE INDEX IF NOT EXISTS articles.idx_articles_language ON articles(language)`,
373+ `CREATE INDEX IF NOT EXISTS articles.idx_likes_article_created ON likes(feed_url, article_url, created_at)`,
374+ `CREATE INDEX IF NOT EXISTS articles.idx_annotations_feed_article_created ON annotations(feed_url, article_url, created_at)`,
375+ `CREATE INDEX IF NOT EXISTS articles.idx_likes_created_author ON likes(created_at, author_did)`,
373376
374377 `CREATE VIRTUAL TABLE IF NOT EXISTS articles.articles_fts USING fts5(title, summary, content, author, content=articles, content_rowid=id)`,
375378 `CREATE TRIGGER IF NOT EXISTS articles.articles_ai AFTER INSERT ON articles BEGIN
@@ -370,6 +370,9 @@ var articlesSchema = []string{
370 `CREATE INDEX IF NOT EXISTS articles.idx_likes_author ON likes(author_did)`,370 `CREATE INDEX IF NOT EXISTS articles.idx_likes_author ON likes(author_did)`,
371 `CREATE INDEX IF NOT EXISTS articles.idx_likes_created_at ON likes(created_at DESC)`,371 `CREATE INDEX IF NOT EXISTS articles.idx_likes_created_at ON likes(created_at DESC)`,
372 `CREATE INDEX IF NOT EXISTS articles.idx_articles_language ON articles(language)`,372 `CREATE INDEX IF NOT EXISTS articles.idx_articles_language ON articles(language)`,
373+ `CREATE INDEX IF NOT EXISTS articles.idx_likes_article_created ON likes(feed_url, article_url, created_at)`,
374+ `CREATE INDEX IF NOT EXISTS articles.idx_annotations_feed_article_created ON annotations(feed_url, article_url, created_at)`,
375+ `CREATE INDEX IF NOT EXISTS articles.idx_likes_created_author ON likes(created_at, author_did)`,
373 376
374 `CREATE VIRTUAL TABLE IF NOT EXISTS articles.articles_fts USING fts5(title, summary, content, author, content=articles, content_rowid=id)`,377 `CREATE VIRTUAL TABLE IF NOT EXISTS articles.articles_fts USING fts5(title, summary, content, author, content=articles, content_rowid=id)`,
375 `CREATE TRIGGER IF NOT EXISTS articles.articles_ai AFTER INSERT ON articles BEGIN378 `CREATE TRIGGER IF NOT EXISTS articles.articles_ai AFTER INSERT ON articles BEGIN