Skip to main content

Query & update language

LioranDB's embedded query engine uses plain JavaScript objects.

Text search ($text)

Text search is available when you create one or more text indexes (see Indexes & explain).

Use $text at the top level of your filter:

// minimal form (search all text-indexed fields)
{ $text: "hello world" }

or:

{
$text: {
$search: "hello world",
// optional: restrict to these text-indexed fields
$fields: ["title", "body"],
}
}

Notes:

  • $text is used as a candidate pre-filter and then the rest of the query runs normally.
  • When $fields is provided, all listed fields must have a text index.

Dates and timestamps

LioranDB documents are persisted as JSON. In Node.js, if you insert a Date, JSON.stringify() converts it to an ISO string.

Recommendations:

  • Prefer storing timestamps as number (epoch milliseconds) using Date.now() for easy $gte/$lte range queries.
  • If you store ISO strings, range queries compare strings (lexicographic), so always use full ISO-8601 format.

Query basics

  • A query is usually an object: { field: value }
  • Keys can be dot-paths: "profile.age", "stats.logins"
  • Multiple keys mean "AND" (all conditions must match)

Equality

{ email: "a@b.com" }
Sandbox output (example)
Matches docs where doc.email === "a@b.com"

Dot-paths

{ "profile.age": 21 }
Sandbox output (example)
Matches docs where doc.profile?.age === 21

Operators (for a field x)

Supported operators:

  • $gt, $gte
  • $lt, $lte
  • $ne, $eq
  • $in (array membership)

Range

{ age: { $gte: 18, $lt: 65 } }
Sandbox output (example)
Matches 18 <= doc.age < 65

$in

{ status: { $in: ["active", "trial"] } }
Sandbox output (example)
Matches docs where status is one of "active" or "trial"

Combine multiple fields (implicit AND)

{ plan: "pro", "profile.age": { $gte: 18 } }
Sandbox output (example)
Matches docs that satisfy both conditions

Functional queries

You can also pass a function instead of an object:

(doc) => doc.qty > 0 && doc.sku?.startsWith("A")
Sandbox output (example)
Matches docs where qty > 0 and sku begins with "A"

Find options: limit, offset, projection

await collection.find(
{ plan: "pro" },
{ limit: 10, offset: 0, projection: ["email", "profile.age"] }
)
  • limit: max documents returned
  • offset: skip N matching docs (simple paging)
  • projection: include only specific fields (top-level or dot-paths)
Sandbox output (example)
[ { email: "a@b.com", profile: { age: 21 } }, { email: "c@d.com", profile: { age: 35 } } ]

Updates

Updates can be either:

  1. Operator updates (contain $ keys), or
  2. Replacement/merge updates (no $ keys)

Operator updates

$set

{ $set: { "profile.name": "New Name", plan: "pro" } }
Sandbox output (example)
Sets profile.name and plan on the matching doc(s)

$inc

{ $inc: { attempts: 1, "stats.logins": 1 } }
Sandbox output (example)
Increments numeric fields by the given amount

Replacement/merge updates (no $ keys)

If the update object contains no $ keys, it's treated as a shallow merge:

{ status: "active", plan: "pro" }
Sandbox output (example)
Merges into the existing doc (top-level keys)

Upserts

updateOne(filter, update, { upsert: true }) inserts a new document if nothing matches.

await users.updateOne(
{ email: "new@x.com" },
{ $set: { email: "new@x.com", plan: "free" } },
{ upsert: true }
)
Sandbox output (example)
Inserts a new doc when no existing doc matches the filter

Complete example (query + update)

import { LioranManager } from "@liorandb/core";

const manager = new LioranManager({ rootPath: "./.liorandb" });
const db = await manager.db("app");
const users = db.collection("users");

await users.insertMany([
{ email: "a@b.com", profile: { age: 21 }, plan: "free" },
{ email: "c@d.com", profile: { age: 35 }, plan: "pro" },
]);

await users.updateOne(
{ "profile.age": { $gte: 18 }, plan: { $in: ["free", "pro"] } },
{ $inc: { "stats.logins": 1 }, $set: { active: true } }
);

console.log(await users.find({}, { projection: ["email", "stats.logins", "active"] }));
await manager.close();
Sandbox output (example)
[ { email: "a@b.com", stats: { logins: 1 }, active: true }, { email: "c@d.com" } ]