Skip to main content

Migrating from Elasticsearch

If you are coming from Elasticsearch or OpenSearch, most search features map onto SereneDB's inverted index and plain SQL. This page maps the concepts side by side; each Elasticsearch feature links to its reference. The biggest shift is that search and analytics are both just SQL — you filter with @@ and aggregate with GROUP BY in the same query, against the same database that holds your relational data.

Key differences

AspectElasticsearchSereneDB
Query languageQuery DSL (JSON)SQL — @@, ORDER BY, GROUP BY
Data modelDocuments in indicesRows in tables, with an inverted index beside the columnar data
Schema & typesDynamic field mappings, JSON typesTyped SQL columns; per-column operator classes pick how each is indexed
Search typesSeparate field types — text, dense_vector, geo_*One inverted index spans full-text, vector and geospatial
Analyzer configAnalyzers, tokenizers, token filtersText search dictionaries — templates + pipeline
RelevanceBM25 by defaultBM25 by default, plus other scorers
Aggregations + hitsOne request, two result treesOne SQL query — filter + GROUP BY / window
TransactionsNone across documentsFull ACID
JoinsLimited (nested / parent-child)Native SQL joins
DeploymentDistributed JVM clusterSingle binary, PostgreSQL wire protocol

Migration tips

Query capabilities

ElasticsearchSereneDBNotes
matchcol @@ 'terms' (Full-Text Search)
match_phrase / proximityts_phrase, ## operator
prefix / wildcard / regexpts_starts_with, ts_like, ts_regexp
fuzzyts_levenshtein; plus ts_ngram n-gram similarity (no ES equivalent)
bool&& || !!, ts_compound
term / termsverbatim columns; ts_any / ts_all
rangets_between, ts_lt/le/gt/ge
query_stringto_tsquery, websearch_to_tsquery
more_like_this⚠️No direct function; use minhash or vector similarity

Function mapping

The detailed mapping from each Elasticsearch query to the specific SereneDB function — the left column links to the Elasticsearch reference, the right to the SereneDB function reference:

Elasticsearch querySereneDB function
matcha bare string, or ts_tokenize
match (operator: and)plainto_tsquery
match_phrasets_phrase / phraseto_tsquery
match_phrase (slop)## / tsquery_phrase
prefixts_starts_with
wildcardts_like
regexpts_regexp
fuzzyts_levenshtein
(no ES equivalent)ts_ngram — n-gram similarity
term / termsa verbatim token, ts_any / ts_all
terms_setts_any with min_match
rangets_between, ts_lt / ts_le / ts_gt / ts_ge
existsts_is_not_null / ts_is_null
boolts_compound, or && / || / !!
query_stringto_tsquery
simple_query_stringwebsearch_to_tsquery
boost (^)^ operator
_score (BM25)BM25 and other scorers
highlightingts_highlight, ts_offsets
kNN<-> / <=> / <#> + ORDER BY … LIMIT
geo queriesST_Intersects, ST_Contains, ST_Distance_*
analyzer testts_lexize

Text analysis

ElasticsearchSereneDBNotes
Tokenizerstext, ngram, delimiter, segmentation, … templates
Token filters (lowercase / stemming / stopwords)text template options + stem / stopwords templates
Accent foldingaccent = false
n-gram / edge n-gramngram, sparse_ngram
Synonymssolr_synonyms, wordnet_synonyms
Custom analyzerscompose templates with pipeline
Separate search analyzerSymmetric by default; override per query with ts_tokenize(text, 'dict') or 'text'::tokenize('dict')

Scoring and relevance

ElasticsearchSereneDBNotes
BM25BM25(idx.tableoid) (Ranking)
Other scorersTFIDF, lm_jm, lm_dirichlet, dfi, more
boosting / boost^ operator (Boosting)
function_scorecompose the scorer in SQL arithmetic, e.g. BM25(...) * 2
Top-K accelerationoptimize_top_k (WAND)
Reciprocal Rank FusionHybrid Search + RRF

Highlighting

ElasticsearchSereneDBNotes
Snippets / fragmentsts_highlight
Custom tagsStartSel / StopSel
Match offsetsts_offsets

Vector and geospatial

ElasticsearchSereneDBNotes
Dense vector / kNN (HNSW)Vector Search
Geo queriesGeospatial Search (ST_*)

Aggregations

This is where SereneDB's SQL model shines: every Elasticsearch aggregation maps to a SQL construct, run in the same query as the search filter. Elasticsearch's three families map as follows.

Bucket aggregations

Bucket aggregations group documents into buckets — SereneDB's GROUP BY clause:

ElasticsearchSereneDB
terms / multi_termsGROUP BY col (one or more columns)
histogramGROUP BY width_bucket(col, …)
date_histogramGROUP BY date_trunc('month', col)
range / date_range / ip_rangeGROUP BY CASE …
filterWHERE …
filterscount(*) with a FILTER clause per branch
missingWHERE col IS NULL
rare_termsGROUP BY col with HAVING count(*) <= n
nestedUNNEST / LATERAL

Metric aggregations

Metric aggregations compute a value over each bucket — SereneDB's aggregate functions:

ElasticsearchSereneDB
avg / sum / min / max / value_countavg / sum / min / max / count
stats / extended_statsthose together (+ stddev / variance)
cardinalityapprox_count_distinct(col) (or count(DISTINCT col))
percentilesquantile_cont(col, p)
percentile_rankscount(*) FILTER (WHERE col <= v) / count(*)
weighted_avgsum(w*x) / sum(w)
top_hitsDISTINCT ON / windowed row_number()

Pipeline aggregations

Pipeline aggregations post-process the output of other aggregations — SereneDB's window functions:

ElasticsearchSereneDB
cumulative_sumsum(x) OVER (ORDER BY …)
derivative / serial_diffx - lag(x) OVER (…)
moving_fnavg(x) OVER (… ROWS BETWEEN …)
bucket_scriptarithmetic over aggregated columns
bucket_selectorHAVING
bucket_sortORDER BY LIMIT

Aggregates run over the inverted index itselfGROUP BY and aggregate functions over indexed (and INCLUDEd) columns are answered without materializing the base table. Add columns you frequently aggregate to the index. The query below filters with @@ and buckets the matches by category in one statement — the Elasticsearch equivalent of a terms aggregation inside a query:

Query
SELECT category, count(*) AS nFROM catalog_docs_idxWHERE body @@ 'galaxy'GROUP BY categoryORDER BY category;
Result
 category | n----------+--- guide    | 1 sci-fi   | 2

Index management and operations

ElasticsearchSereneDBNotes
Create / delete indexCREATE INDEX … USING inverted / DROP INDEX
ReindexDROP INDEX + CREATE INDEX
RefreshVACUUM (REFRESH_TABLE) (Maintenance)
Force mergeVACUUM (COMPACT_TABLE)
AliasesUse a view
Pagination (from/size, search_after)LIMIT / OFFSET, keyset pagination

See also