Indexing Views
An inverted index in SereneDB is a named relation, and you can build it on a view just as easily as on a table. That is the hook for searching anything a view can express: a projection of a table, a join, a union or a pile of Parquet and CSV files. You point the index at the view and query the index relation, and every search feature works the same as on a table.
Schema and sample data
CREATE TEXT SEARCH DICTIONARY en ( template = 'text', locale = 'en_US.UTF-8', case = 'lower', stemming = false, accent = false, frequency = true, position = true);
CREATE TABLE docs (id INTEGER PRIMARY KEY, body VARCHAR, category VARCHAR);
INSERT INTO docs VALUES(1, 'quick brown fox', 'animal'),(2, 'lazy dog sleeps', 'animal'),(3, 'quick red fox', 'animal'),(4, 'distributed sql engine', 'tech'),(5, 'quick sql query', 'tech');
CREATE VIEW v_docs AS SELECT id, body, category FROM docs;
CREATE INDEX v_docs_idx ON v_docs USING inverted (id, body en, category);Index a view and search it
Build the index on the view with CREATE INDEX ... ON v_docs USING inverted(...), then query the index relation v_docs_idx. Full-text @@ and BM25 ranking work exactly as they do on a table-backed index.
SELECT id, bodyFROM v_docs_idxWHERE body @@ 'quick'ORDER BY BM25(v_docs_idx.tableoid) DESC, id; id | body----+----------------- 1 | quick brown fox 3 | quick red fox 5 | quick sql queryFacet through it
GROUP BY and the ts_dict_* aggregates read that same index, so faceting a search over a view is no different from faceting one over a table.
SELECT category, count(*) AS nFROM v_docs_idxWHERE body @@ 'quick'GROUP BY categoryORDER BY category; category | n----------+--- animal | 2 tech | 1A reusable saved search
Wrap a search in a view and it becomes a named query you point applications at. Callers add their own predicates on top and they fuse into the same index scan, so recent_hits filtered by category stays a single indexed lookup, not a scan over the results. Re-point it with CREATE OR REPLACE VIEW when you want the name to follow a new search, which is how you stand in for an index alias.
SELECT id, bodyFROM recent_hitsWHERE category = 'animal'ORDER BY id; id | body----+----------------- 1 | quick brown fox 3 | quick red foxNo materialized views
SereneDB has no MATERIALIZED VIEW. You do not need one here: an index built on a view over a base table already holds a postings snapshot that only moves when you refresh or rebuild, which covers the usual reason to reach for a materialized view in the first place.
See also
- Indexing Views: the reference on building an index over a view, including the
pkrule for union and join views - Indexing External Data: the real payoff, an index over a view of Parquet, CSV or S3 files
- Migrating from Elasticsearch: where index aliases map to views