EventsDB: expandFilters, greatly speed up domain timelines
Fixes: https://gitlab.com/soapbox-pub/ditto/-/issues/80
This commit is contained in:
parent
c3adafa860
commit
cfc2f02104
|
@ -193,26 +193,9 @@ class EventsDB implements NStore {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filter.search) {
|
if (filter.search) {
|
||||||
const tokens = NIP50.parseInput(filter.search);
|
query = query
|
||||||
|
.innerJoin('events_fts', 'events_fts.id', 'events.id')
|
||||||
const domain = (tokens.find((t) =>
|
.where('events_fts.content', 'match', JSON.stringify(filter.search));
|
||||||
typeof t === 'object' && t.key === 'domain'
|
|
||||||
) as { key: 'domain'; value: string } | undefined)?.value;
|
|
||||||
|
|
||||||
if (domain) {
|
|
||||||
query = query.where('events.pubkey', 'in', (eb) =>
|
|
||||||
eb.selectFrom('pubkey_domains').select('pubkey').where('domain', '=', domain));
|
|
||||||
}
|
|
||||||
|
|
||||||
const q = tokens.filter((t) =>
|
|
||||||
typeof t === 'string'
|
|
||||||
).join(' ');
|
|
||||||
|
|
||||||
if (q) {
|
|
||||||
query = query
|
|
||||||
.innerJoin('events_fts', 'events_fts.id', 'events.id')
|
|
||||||
.where('events_fts.content', 'match', JSON.stringify(q));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return query;
|
return query;
|
||||||
|
@ -234,9 +217,47 @@ class EventsDB implements NStore {
|
||||||
.as('users');
|
.as('users');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Converts filters to more performant, simpler filters that are better for SQLite. */
|
||||||
|
async expandFilters(filters: NostrFilter[]): Promise<NostrFilter[]> {
|
||||||
|
filters = normalizeFilters(filters); // Improves performance of `{ kinds: [0], authors: ['...'] }` queries.
|
||||||
|
|
||||||
|
for (const filter of filters) {
|
||||||
|
if (filter.search) {
|
||||||
|
const tokens = NIP50.parseInput(filter.search);
|
||||||
|
|
||||||
|
const domain = (tokens.find((t) =>
|
||||||
|
typeof t === 'object' && t.key === 'domain'
|
||||||
|
) as { key: 'domain'; value: string } | undefined)?.value;
|
||||||
|
|
||||||
|
if (domain) {
|
||||||
|
const query = this.#db
|
||||||
|
.selectFrom('pubkey_domains')
|
||||||
|
.select('pubkey')
|
||||||
|
.where('domain', '=', domain);
|
||||||
|
|
||||||
|
if (filter.authors) {
|
||||||
|
query.where('pubkey', 'in', filter.authors);
|
||||||
|
}
|
||||||
|
|
||||||
|
const pubkeys = await query
|
||||||
|
.execute()
|
||||||
|
.then((rows) =>
|
||||||
|
rows.map((row) => row.pubkey)
|
||||||
|
);
|
||||||
|
|
||||||
|
filter.authors = pubkeys;
|
||||||
|
}
|
||||||
|
|
||||||
|
filter.search = tokens.filter((t) => typeof t === 'string').join(' ');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return filters;
|
||||||
|
}
|
||||||
|
|
||||||
/** Get events for filters from the database. */
|
/** Get events for filters from the database. */
|
||||||
async query(filters: NostrFilter[], opts: NStoreOpts = {}): Promise<DittoEvent[]> {
|
async query(filters: NostrFilter[], opts: NStoreOpts = {}): Promise<DittoEvent[]> {
|
||||||
filters = normalizeFilters(filters); // Improves performance of `{ kinds: [0], authors: ['...'] }` queries.
|
filters = await this.expandFilters(filters);
|
||||||
|
|
||||||
if (opts.signal?.aborted) return Promise.resolve([]);
|
if (opts.signal?.aborted) return Promise.resolve([]);
|
||||||
if (!filters.length) return Promise.resolve([]);
|
if (!filters.length) return Promise.resolve([]);
|
||||||
|
|
Loading…
Reference in New Issue