Queries

July 11, 2026 ยท View on GitHub

The fluent QueryBuilder pushes conditions down to MongrelDB's native indexes for sub-millisecond lookups - bitmap, learned-range, FM-index full text, HNSW vector similarity, and more. Each condition type maps to one specialized index; conditions are AND-ed together.

let q =
  db
  |> mongreldb.query("orders")
  |> mongreldb.where_("range", [
    #("column", mongreldb.int_value(3)),
    #("min", mongreldb.float_value(100.0)),
    #("max", mongreldb.float_value(500.0)),
  ])
  |> mongreldb.projection([1, 2])
  |> mongreldb.limit_(100)
let assert Ok(rows) = mongreldb.execute(q)

This guide covers every condition type, projection, limits, combining conditions, and the friendly aliases the builder translates for you.


The basics

Every query starts with mongreldb.query(db, table) and ends with execute:

MethodPurpose
where_(qb, type, params)Add a native condition. Multiple where_ calls are AND-ed.
projection(qb, column_ids)Return only these column ids (omit for all columns).
limit_(qb, n)Cap the number of rows.
execute(qb)Send and decode.

The request body produced by the builder matches the daemon's /kit/query shape:

{
  "table": "orders",
  "conditions": [{"range": {"column_id": 3, "lo": 100.0, "hi": 500.0}}],
  "projection": [1, 2],
  "limit": 100
}

Condition types

params is a list of #(String, Value). Column references use the numeric column id, never the column name.

pk - exact primary-key match

The fastest lookup. value is the primary-key value.

let q =
  db
  |> mongreldb.query("orders")
  |> mongreldb.where_("pk", [#("value", mongreldb.int_value(42))])
let assert Ok(_) = mongreldb.execute(q)

range - integer range (learned-range index)

Inclusive bounds. Omit lo (min) or hi (max) for an open range.

let q =
  db
  |> mongreldb.query("orders")
  |> mongreldb.where_("range", [
    #("column", mongreldb.int_value(3)),
    #("min", mongreldb.int_value(100)),
    #("max", mongreldb.int_value(500)),
  ])
let assert Ok(_) = mongreldb.execute(q)

range_f64 - float range with inclusive/exclusive control

Adds lo_inclusive / hi_inclusive flags (default inclusive).

let q =
  db
  |> mongreldb.query("orders")
  |> mongreldb.where_("range_f64", [
    #("column", mongreldb.int_value(3)),
    #("min", mongreldb.float_value(100.0)),
    #("max", mongreldb.float_value(500.0)),
    #("min_inclusive", mongreldb.bool_value(True)),
    #("max_inclusive", mongreldb.bool_value(False)), // (100.0, 500.0]
  ])
let assert Ok(_) = mongreldb.execute(q)

bitmap_eq - equality on a bitmap-indexed column

Best for low-cardinality columns (status, category, booleans).

let q =
  db
  |> mongreldb.query("orders")
  |> mongreldb.where_("bitmap_eq", [
    #("column", mongreldb.int_value(2)),
    #("value", mongreldb.string_value("Alice")),
  ])
let assert Ok(_) = mongreldb.execute(q)

is_null / is_not_null - null checks

let q =
  db
  |> mongreldb.query("orders")
  |> mongreldb.where_("is_null", [#("column", mongreldb.int_value(3))])
let assert Ok(_) = mongreldb.execute(q)

fm_contains - full-text substring search (FM-index)

Substring match within a column. Use pattern (the server key) or the friendly value alias - both translate to pattern on the wire for FTS conditions.

let q =
  db
  |> mongreldb.query("documents")
  |> mongreldb.where_("fm_contains", [
    #("column", mongreldb.int_value(2)),
    #("pattern", mongreldb.string_value("database performance")),
  ])
  |> mongreldb.limit_(10)
let assert Ok(_) = mongreldb.execute(q)

ann - dense vector similarity (HNSW)

Approximate nearest-neighbors over a vector column. k is the result count.

import gleam/dynamic

let vec = [
  mongreldb.float_value(0.1),
  mongreldb.float_value(0.2),
  mongreldb.float_value(0.3),
  mongreldb.float_value(0.4),
]

let q =
  db
  |> mongreldb.query("embeddings")
  |> mongreldb.where_("ann", [
    #("column", mongreldb.int_value(2)),
    #("query", dynamic.from(vec)),
    #("k", mongreldb.int_value(10)),
  ])
let assert Ok(_) = mongreldb.execute(q)

Projection (column selection)

projection(qb, [1, 2]) restricts the columns in each returned row. Omit the call for all columns. Projecting to only the columns you need cuts bandwidth and decode cost.

let q =
  db
  |> mongreldb.query("orders")
  |> mongreldb.where_("range", [#("column", mongreldb.int_value(3)), #("min", mongreldb.int_value(100))])
  |> mongreldb.projection([1, 2])
let assert Ok(_) = mongreldb.execute(q)

Limit

limit_(qb, n) caps the result.

let q =
  db
  |> mongreldb.query("orders")
  |> mongreldb.where_("range", [#("column", mongreldb.int_value(3)), #("min", mongreldb.int_value(100))])
  |> mongreldb.limit_(100)
let assert Ok(rows) = mongreldb.execute(q)

Multiple AND conditions

Chain where_ calls. Every condition must match; the server intersects the index results.

let q =
  db
  |> mongreldb.query("orders")
  |> mongreldb.where_("bitmap_eq", [
    #("column", mongreldb.int_value(2)),
    #("value", mongreldb.string_value("Alice")),
  ])
  |> mongreldb.where_("range", [
    #("column", mongreldb.int_value(3)),
    #("min", mongreldb.int_value(100)),
    #("max", mongreldb.int_value(500)),
  ])
  |> mongreldb.projection([1, 3])
  |> mongreldb.limit_(50)
let assert Ok(_) = mongreldb.execute(q)

Friendly alias translation

The builder accepts readable parameter names and translates them to the server's canonical on-wire keys. Both spellings work, so use whichever is clearer in context.

You writeSent asApplies to
columncolumn_idall condition types
minlorange, range_f64
maxhirange, range_f64
min_inclusivelo_inclusiverange_f64
max_inclusivehi_inclusiverange_f64
valuepatternfm_contains, fm_contains_all only

The value -> pattern alias applies only to FTS conditions, because pk and bitmap_eq use value as their canonical key. For those, write value directly.

For arbitrary predicates, joins, and aggregations that the native indexes do not cover, use SQL instead - see sql.md.