Complete statement reference for the QQL query language.
Collection Management
Section titled “Collection Management”-- CreateCREATE COLLECTION <name>CREATE COLLECTION <name> HYBRIDCREATE COLLECTION <name> HYBRID RERANKCREATE COLLECTION <name> USING MODEL '<model>'CREATE COLLECTION <name> (name VECTOR(size, DISTANCE), ...)
-- ConfigCREATE COLLECTION <name> WITH HNSW (m = 32, ef_construct = 100)CREATE COLLECTION <name> WITH QUANTIZATION (type = 'scalar', quantile = 0.95)CREATE COLLECTION <name> WITH QUANTIZATION (type = 'turbo', bits = 2, always_ram = true)CREATE COLLECTION <name> WITH QUANTIZATION (type = 'binary', always_ram = true)CREATE COLLECTION <name> WITH QUANTIZATION (type = 'product')
-- Per-vector configCREATE COLLECTION docs ( dense VECTOR(384, COSINE) WITH QUANTIZATION (type = 'scalar'), sparse VECTOR(768, DOT))
-- Multivector (ColBERT / ColPali) with HNSW disabled for rerankingCREATE COLLECTION docs ( dense VECTOR(384, COSINE), colbert VECTOR(128, COSINE) WITH MULTIVECTOR (comparator = 'max_sim') WITH HNSW (m = 0))
-- PDF retrieval: 3 named vectors (indexed + reranking)CREATE COLLECTION pdf_retrieval ( original VECTOR(128, COSINE) WITH MULTIVECTOR (comparator = 'max_sim') WITH HNSW (m = 0), mean_pooling_columns VECTOR(128, COSINE) WITH MULTIVECTOR (comparator = 'max_sim'), mean_pooling_rows VECTOR(128, COSINE) WITH MULTIVECTOR (comparator = 'max_sim'))
-- AlterALTER COLLECTION <name> WITH VECTORS (on_disk = true)ALTER COLLECTION <name> WITH HNSW (m = 32)ALTER COLLECTION <name> WITH OPTIMIZERS (max_segment_size = 500000)ALTER COLLECTION <name> WITH PARAMS (replication_factor = 3)ALTER COLLECTION <name> WITH QUANTIZATION (type = 'scalar')ALTER COLLECTION <name> WITH QUANTIZATION (disabled = true)
-- Drop / ShowDROP COLLECTION <name>SHOW COLLECTIONSSHOW COLLECTION <name>Indexes
Section titled “Indexes”CREATE INDEX ON COLLECTION <name> FOR <field> TYPE keywordCREATE INDEX ON COLLECTION <name> FOR <field> TYPE integerCREATE INDEX ON COLLECTION <name> FOR <field> TYPE floatCREATE INDEX ON COLLECTION <name> FOR <field> TYPE boolCREATE INDEX ON COLLECTION <name> FOR <field> TYPE uuidCREATE INDEX ON COLLECTION <name> FOR <field> TYPE datetimeCREATE INDEX ON COLLECTION <name> FOR <field> TYPE geo
-- With optionsCREATE INDEX ON docs FOR tags TYPE keyword WITH (is_tenant = true, on_disk = true, enable_hnsw = false)CREATE INDEX ON docs FOR content TYPE text WITH (tokenizer = 'word', min_token_len = 2, max_token_len = 20, lowercase = true, phrase_matching = true, stopwords = ['en'])INSERT
Section titled “INSERT”INSERT INTO <name> VALUES {'id': 1, 'text': 'hello', 'field': 'value'}INSERT INTO <name> VALUES {'id': 1, 'text': 'hello'}, {'id': 2, 'text': 'world'}INSERT INTO <name> VALUES {'id': 1, 'text': 'hello'} USING HYBRIDINSERT INTO <name> VALUES {'id': 1, 'text': 'hello'} USING MODEL '<model>'INSERT INTO <name> VALUES {'id': 1, 'text': 'hello'} USING HYBRID DENSE MODEL '<m1>' SPARSE MODEL '<m2>'
-- Insert with pre-computed named vectors (dense + multivector)INSERT INTO docs VALUES {'id': 1, 'text': 'hello', 'vector': {'dense': [0.1, 0.2, 0.3], 'colbert': [[0.1, 0.2], [0.3, 0.4]]}}Field rules:
id— required. Must be an unsigned integer or UUID string.text— required for auto-vectorization.vector— stores pre-computed vectors. Use a map of named vectors for multi-vector collections. Each value can be a 1D array (dense) or 2D array (multivector).
The unified query statement with multiple modes.
NEAREST (default)
Section titled “NEAREST (default)”QUERY '<text>' FROM <collection> LIMIT <n>QUERY '<text>' FROM <collection> LIMIT <n> OFFSET <n>QUERY '<text>' FROM <collection> LIMIT <n> SCORE THRESHOLD 0.5QUERY '<text>' FROM <collection> LIMIT <n> LOOKUP FROM <other> [VECTOR '<name>']QUERY '<text>' FROM <collection> LIMIT <n> USING MODEL '<model>'QUERY [0.1, 0.2, 0.3] FROM <collection> LIMIT <n>Hybrid
Section titled “Hybrid”QUERY '<text>' FROM <collection> LIMIT <n> USING HYBRIDQUERY '<text>' FROM <collection> LIMIT <n> USING HYBRID FUSION DBSFQUERY '<text>' FROM <collection> LIMIT <n> USING HYBRID WITH (rrf_k = 30, rrf_weights = [0.7, 0.3])Sparse / Dense
Section titled “Sparse / Dense”QUERY '<text>' FROM <collection> LIMIT <n> USING SPARSEQUERY '<text>' FROM <collection> LIMIT <n> USING DENSERecommend
Section titled “Recommend”QUERY RECOMMEND WITH (positive = ('id-1', 'id-2')) FROM <collection> LIMIT <n>QUERY RECOMMEND WITH (positive = ('id-1'), negative = ('id-3')) FROM <collection> LIMIT <n>QUERY RECOMMEND WITH (positive = ('id-1')) STRATEGY 'best_score' FROM <collection> LIMIT <n>Strategies: average_vector, best_score, sum_scores.
Context and Discover
Section titled “Context and Discover”QUERY CONTEXT PAIRS (('id-1', 'id-2'), ('id-3', 'id-4')) FROM <collection> LIMIT <n>QUERY DISCOVER TARGET 'id-1' CONTEXT PAIRS (('id-2', 'id-3')) FROM <collection> LIMIT <n>ORDER BY
Section titled “ORDER BY”QUERY ORDER BY <field> ASC FROM <collection> LIMIT <n>QUERY ORDER BY <field> DESC FROM <collection> LIMIT <n>SAMPLE
Section titled “SAMPLE”QUERY SAMPLE FROM <collection> LIMIT <n>QUERY SAMPLE FROM <collection> LIMIT <n> WHERE <filter>CTEs and Prefetch DAGs
Section titled “CTEs and Prefetch DAGs”WITH dense AS (QUERY [0.1, 0.2, 0.3] USING 'dense' LIMIT 200), sparse AS (QUERY [0.1, 0.2, 0.3] USING 'sparse' LIMIT 300)QUERY '<query>' FROM <collection> USING 'colbert' LIMIT 10 PREFETCH (dense, sparse)
-- Per-prefetch filters and score thresholdsWITH dense AS (QUERY 'search' USING dense LIMIT 200 WHERE category = 'tech'), sparse AS (QUERY 'search' USING sparse LIMIT 300)QUERY 'search' FROM <collection> LIMIT 10 PREFETCH ( dense WHERE priority = 'high' SCORE THRESHOLD 0.6, sparse SCORE THRESHOLD 0.3 ) FUSION RRF WITH (rrf_k = 20, rrf_weights = [0.6, 0.4])
-- Pure fusion (no search target, just fuse CTE results)FUSION RRF LIMIT 10 PREFETCH (dense, sparse)
-- Pure fusion with CTEsWITH _pf0 AS (QUERY 'search' USING 'dense' LIMIT 100), _pf1 AS (QUERY 'search' USING 'sparse' LIMIT 100)FUSION RRF LIMIT 10 PREFETCH (_pf0, _pf1)CTEs can reference previously defined CTEs for nested prefetch DAGs.
Clauses
Section titled “Clauses”| Clause | Description |
|---|---|
LIMIT <n> | Max results (default 10) |
OFFSET <n> | Skip first N results |
SCORE THRESHOLD <float> | Minimum score filter |
LOOKUP FROM <col> [VECTOR '<name>'] | Cross-collection vector lookup |
WHERE <filter> | Payload filter |
USING HYBRID | Dense + sparse fusion |
USING SPARSE | Sparse-only |
USING DENSE | Dense-only |
USING MODEL '<model>' | Pin dense model |
EXACT | Exact KNN (no HNSW) |
RERANK [MODEL '<model>'] | Cloud reranking |
GROUP BY '<field>' [GROUP_SIZE <n>] | Grouped results |
WITH LOOKUP FROM <col> | Cross-collection group ID lookup |
STRATEGY '<strategy>' | Recommend strategy |
BOOST (<expr>) | Score shaping |
DEFAULTS (key = value) | Formula variable defaults |
WITH params
Section titled “WITH params”WITH (hnsw_ef = 256)WITH (exact = true)WITH (acorn = true)WITH (indexed_only = true)WITH (mmr_diversity = 0.5, mmr_candidates = 20)WITH (rrf_k = 30, rrf_weights = [0.7, 0.3])WITH PAYLOAD (include = ['title', 'body'])WITH PAYLOAD (exclude = ['embedding'])WITH PAYLOAD falseWITH VECTORS ('dense', 'sparse')WITH VECTORS trueWITH MODEL '<model>'WITH LOOKUP FROM <collection>Multiple WITH clauses merge: WITH MODEL 'x' WITH PAYLOAD (include = ['a']) WITH (exact = true)
BOOST (Score Shaping)
Section titled “BOOST (Score Shaping)”QUERY '<text>' FROM <collection> LIMIT <n> BOOST (<expression>) DEFAULTS (key = value, ...)Expression syntax
Section titled “Expression syntax”-- Arithmetic$score * 2 + 1a + b - c * d / ea / b [default=1.0] -- division with zero-safety default
-- Math functionsABS(x) | SQRT(x) | LOG(x) | LN(x) | EXP(x) | POW(base, exponent)
-- Geo distanceGEO_DISTANCE({lat: 40.7, lon: -74.0}, location_field)
-- Decay functionsGAUSS_DECAY(field, target: value, scale: 30d)EXP_DECAY(field, target: value, scale: 30d)LIN_DECAY(field, target: value, scale: 30d)GAUSS_DECAY(field, target: datetime('2026-01-01'), scale: 30d, midpoint: 0.5)
-- Datetimedatetime('2026-01-01T00:00:00Z')datetime_key('published_at')
-- ConditionalCASE WHEN <filter> THEN <expr> ELSE <expr> END
-- Variables$score -- current relevance scorefield_name -- payload field valueSELECT / SCROLL
Section titled “SELECT / SCROLL”SELECT * FROM <collection> WHERE id = '<uuid>'SELECT * FROM <collection> WHERE id = <integer>
SCROLL FROM <collection> LIMIT <n>SCROLL FROM <collection> WHERE <filter> LIMIT <n>SCROLL FROM <collection> AFTER '<point_id>' LIMIT <n>SCROLL FROM <collection> WHERE <filter> AFTER <point_id> LIMIT <n>UPDATE
Section titled “UPDATE”UPDATE <collection> SET PAYLOAD = {'field': 'value'} WHERE id = '<uuid>'UPDATE <collection> SET PAYLOAD = {'field': 'value'} WHERE <filter>UPDATE <collection> SET VECTOR = [0.1, 0.2, 0.3] WHERE id = '<uuid>'UPDATE <collection> SET VECTOR '<name>' = [0.1, 0.2, 0.3] WHERE id = '<uuid>'DELETE
Section titled “DELETE”DELETE FROM <collection> WHERE id = '<uuid>'DELETE FROM <collection> WHERE id = <integer>DELETE FROM <collection> WHERE <field> = '<value>'DELETE FROM <collection> WHERE <filter>EXPLAIN
Section titled “EXPLAIN”qql-go explain "QUERY 'search' FROM docs LIMIT 5 USING HYBRID" qql-go explain --json "QUERY 'search' FROM docs LIMIT 5"Scripts
Section titled “Scripts”qql-go execute <script.qql> qql-go execute --stop-on-error <script.qql> qql-go dump <collection> <output.qql> qql-go dump --batch-size 100 <collection> <output.qql>Scripts are multi-statement QQL files. Statements are separated by newlines. Comments start with --. No semicolons.
Convert (REST JSON → QQL)
Section titled “Convert (REST JSON → QQL)”qql-go convert payload.json echo '{"points":[{"id":1,"payload":{"text":"hi"}}]}' | qql-go convert qql-go convert --validate payload.json qql-go convert --json payload.json qql-go convert --quiet payload.json