use generated columns and gin array indexes to query tags better.
This commit is contained in:
@@ -13,6 +13,12 @@ func initDB(dburl string) (*sqlx.DB, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_, err = db.Exec(`
|
_, 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 (
|
CREATE TABLE IF NOT EXISTS event (
|
||||||
id text NOT NULL,
|
id text NOT NULL,
|
||||||
pubkey text NOT NULL,
|
pubkey text NOT NULL,
|
||||||
@@ -20,14 +26,15 @@ CREATE TABLE IF NOT EXISTS event (
|
|||||||
kind integer NOT NULL,
|
kind integer NOT NULL,
|
||||||
tags jsonb NOT NULL,
|
tags jsonb NOT NULL,
|
||||||
content text 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 ididx ON event (id);
|
||||||
CREATE UNIQUE INDEX IF NOT EXISTS pubkeytimeidx ON event (pubkey, created_at);
|
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)
|
log.Print(err)
|
||||||
return db, nil
|
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, ",")+`)`)
|
conditions = append(conditions, `kind IN (`+strings.Join(inkinds, ",")+`)`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tagQuery := make([]string, 0, 1)
|
||||||
if filter.TagE != nil {
|
if filter.TagE != nil {
|
||||||
if len(filter.TagE) > 10 {
|
if len(filter.TagE) > 10 {
|
||||||
// too many tags, fail everything
|
// too many tags, fail everything
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(filter.TagE) == 0 {
|
if len(filter.TagE) == 0 {
|
||||||
// #e being [] mean you won't get anything
|
// #e being [] mean you won't get anything
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
innerConditions := make([]string, len(filter.TagE))
|
tagQuery = append(tagQuery, filter.TagE...)
|
||||||
for _, e := range filter.TagE {
|
|
||||||
innerConditions = append(innerConditions, tagConditions)
|
|
||||||
params = append(params, e)
|
|
||||||
}
|
}
|
||||||
conditions = append(conditions, strings.Join(innerConditions, " OR "))
|
|
||||||
}
|
|
||||||
|
|
||||||
if filter.TagP != nil {
|
if filter.TagP != nil {
|
||||||
if len(filter.TagP) > 10 {
|
if len(filter.TagP) > 10 {
|
||||||
// too many tags, fail everything
|
// too many tags, fail everything
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(filter.TagP) == 0 {
|
if len(filter.TagP) == 0 {
|
||||||
// #p being [] mean you won't get anything
|
// #e being [] mean you won't get anything
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
innerConditions := make([]string, len(filter.TagP))
|
tagQuery = append(tagQuery, filter.TagP...)
|
||||||
for _, p := range filter.TagP {
|
|
||||||
innerConditions = append(innerConditions, tagConditions)
|
|
||||||
params = append(params, p)
|
|
||||||
}
|
}
|
||||||
conditions = append(conditions, strings.Join(innerConditions, " OR "))
|
|
||||||
|
if len(tagQuery) > 0 {
|
||||||
|
arrayBuild := make([]string, len(tagQuery))
|
||||||
|
for i, tagValue := range tagQuery {
|
||||||
|
arrayBuild[i] = "?"
|
||||||
|
params = append(params, tagValue)
|
||||||
|
}
|
||||||
|
conditions = append(conditions,
|
||||||
|
"tagvalues && ARRAY["+strings.Join(arrayBuild, ",")+"]")
|
||||||
}
|
}
|
||||||
|
|
||||||
if filter.Since != 0 {
|
if filter.Since != 0 {
|
||||||
|
|||||||
Reference in New Issue
Block a user