mirror of
https://github.com/fiatjaf/khatru.git
synced 2025-04-07 11:28:02 +02:00
use generated columns and gin array indexes to query tags better.
This commit is contained in:
parent
ae3f5df0b9
commit
8091dfedbe
@ -13,6 +13,12 @@ func initDB(dburl string) (*sqlx.DB, error) {
|
||||
}
|
||||
|
||||
_, err = db.Exec(`
|
||||
CREATE FUNCTION tags_to_tagvalues(jsonb) RETURNS text[]
|
||||
AS 'SELECT array_agg(t->>1) FROM (SELECT jsonb_array_elements($1) AS t)s;'
|
||||
LANGUAGE SQL
|
||||
IMMUTABLE
|
||||
RETURNS NULL ON NULL INPUT;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS event (
|
||||
id text NOT NULL,
|
||||
pubkey text NOT NULL,
|
||||
@ -20,14 +26,15 @@ CREATE TABLE IF NOT EXISTS event (
|
||||
kind integer NOT NULL,
|
||||
tags jsonb NOT NULL,
|
||||
content text NOT NULL,
|
||||
sig text NOT NULL
|
||||
sig text NOT NULL,
|
||||
|
||||
tagvalues text[] GENERATED ALWAYS AS (tags_to_tagvalues(tags)) STORED
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS ididx ON event (id);
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS pubkeytimeidx ON event (pubkey, created_at);
|
||||
CREATE INDEX IF NOT EXISTS arbitrarytagvalues ON event USING gin (tagvalues);
|
||||
`)
|
||||
log.Print(err)
|
||||
return db, nil
|
||||
}
|
||||
|
||||
const tagConditions = `jsonb_path_match(tags, '$[*][1] == $value', jsonb_build_object('value', ?::text))`
|
||||
|
@ -87,40 +87,38 @@ func (b *BasicRelay) QueryEvents(
|
||||
conditions = append(conditions, `kind IN (`+strings.Join(inkinds, ",")+`)`)
|
||||
}
|
||||
|
||||
tagQuery := make([]string, 0, 1)
|
||||
if filter.TagE != nil {
|
||||
if len(filter.TagE) > 10 {
|
||||
// too many tags, fail everything
|
||||
return
|
||||
}
|
||||
|
||||
if len(filter.TagE) == 0 {
|
||||
// #e being [] mean you won't get anything
|
||||
return
|
||||
}
|
||||
innerConditions := make([]string, len(filter.TagE))
|
||||
for _, e := range filter.TagE {
|
||||
innerConditions = append(innerConditions, tagConditions)
|
||||
params = append(params, e)
|
||||
}
|
||||
conditions = append(conditions, strings.Join(innerConditions, " OR "))
|
||||
tagQuery = append(tagQuery, filter.TagE...)
|
||||
}
|
||||
|
||||
if filter.TagP != nil {
|
||||
if len(filter.TagP) > 10 {
|
||||
// too many tags, fail everything
|
||||
return
|
||||
}
|
||||
|
||||
if len(filter.TagP) == 0 {
|
||||
// #p being [] mean you won't get anything
|
||||
// #e being [] mean you won't get anything
|
||||
return
|
||||
}
|
||||
innerConditions := make([]string, len(filter.TagP))
|
||||
for _, p := range filter.TagP {
|
||||
innerConditions = append(innerConditions, tagConditions)
|
||||
params = append(params, p)
|
||||
tagQuery = append(tagQuery, filter.TagP...)
|
||||
}
|
||||
|
||||
if len(tagQuery) > 0 {
|
||||
arrayBuild := make([]string, len(tagQuery))
|
||||
for i, tagValue := range tagQuery {
|
||||
arrayBuild[i] = "?"
|
||||
params = append(params, tagValue)
|
||||
}
|
||||
conditions = append(conditions, strings.Join(innerConditions, " OR "))
|
||||
conditions = append(conditions,
|
||||
"tagvalues && ARRAY["+strings.Join(arrayBuild, ",")+"]")
|
||||
}
|
||||
|
||||
if filter.Since != 0 {
|
||||
|
Loading…
x
Reference in New Issue
Block a user