Skip to main content

Database, Collections, and Cursors

This page documents the main application-layer handles:

  • Db
  • Collection<TSchema>
  • FindCursor<TSchema>
  • AggregationCursor<TResult>

Db

The Db constructor is created internally by the client, but the public surface is what matters:

  • databaseName
  • collection(name)
  • createCollection(name)
  • listCollections()
  • dropCollection(name)
  • dropDatabase()
  • query(collection, filter?, options?)

databaseName

The selected database name for the handle.

collection(name)

Creates a collection handle.

createCollection(name)

Creates the collection on the server and returns:

type CreateCollectionResult = {
readonly collection: string;
};

listCollections()

Returns a readonly array of collection names.

dropCollection(name)

Convenience wrapper around db.collection(name).drop().

dropDatabase()

Sends a database-drop request for the current database handle.

query(collection, filter?, options?)

This is a database-level query entrypoint that returns a FindCursor.

Collection<TSchema>

This is the main typed document handle.

Creating a typed collection

import {LioranDBClient} from "@liorandb/driver";

type Product = {
_id?: string;
sku: string;
title: string;
price: number;
inStock: boolean;
};

const client = await LioranDBClient.connect(
"liorandb://admin:password@127.0.0.1:27018/default",
);

const db = client.db("default");
const products = db.collection<Product>("products");

Why TypeScript helps

With collection<Product>("products"), TypeScript can:

  • validate inserted document shapes
  • improve autocomplete for fields in filters and projections
  • make result objects easier to use safely

collectionName

Returns the collection name string.

Write methods

insertOne(document, options?)

Signature behavior:

  • document type is OptionalUnlessRequiredId<TSchema>
  • optional idempotencyKey can be supplied

Example:

const result = await products.insertOne(
{
sku: "bk-001",
title: "Blue Notebook",
price: 14,
inStock: true,
},
{idempotencyKey: "product-insert-001"},
);

console.log(result.insertedId);

Representative output:

insertOne output
01K2EXAMPLE

insertMany(documents, options?)

Inserts multiple documents and returns insertedIds.

updateOne(filter, update, options?)

Updates one matching document.

updateMany(filter, update, options?)

Updates every matching document.

deleteOne(filter, options?)

Deletes one matching document.

deleteMany(filter, options?)

Deletes all matching documents.

Read methods

find(filter?, options?)

Returns a FindCursor<TSchema>.

Example:

const docs = await products
.find({inStock: true}, {sort: {price: 1}, limit: 5})
.toArray();

findOne(filter?, options?)

Returns the first matching document or null.

findManyByIds(ids)

Looks up a readonly list of ids and returns a readonly array whose entries are:

  • the document if found
  • null if not found

Aggregation

aggregate(pipeline, options?)

Returns an AggregationCursor<TResult>.

Example:

const results = await products
.aggregate<{_id: string; count: number}>([
{$match: {inStock: true}},
{$group: {_id: "$inStock", count: {$sum: 1}}},
])
.toArray();

console.log(results);

Representative output:

aggregate output
[
{
"_id": true,
"count": 1
}
]

drop(options?)

Drops the collection and returns:

{
readonly collection: string;
}

FindCursor<TSchema>

The source implements FindCursor<TSchema> as:

  • a chainable query-definition object
  • an async iterable
  • a lifecycle-aware cursor that closes if the client closes

Query-shaping methods

  • filter(filter)
  • limit(limit)
  • skip(skip)
  • sort(sort)
  • project(projection)

Each returns a new FindCursor.

Execution methods

  • next()
  • tryNext()
  • hasNext()
  • toArray()

Iteration helpers

  • forEach(iterator)
  • map(mapper)

Lifecycle helpers

  • rewind()
  • clone()
  • close()

next()

Reads the next document or returns null.

toArray()

Drains the remaining cursor contents and returns a readonly array.

forEach()

Runs an async or sync callback for every document.

map()

Transforms cursor results and returns a readonly array of mapped results.

rewind()

Resets the cursor’s consumed position and fetch state.

clone()

Creates a fresh cursor with the same definition.

Mutation rule

Once execution starts, query-shaping methods can no longer mutate the cursor. If you try to change the query after execution starts, the source throws CursorInitializedError.

Representative example:

Cursor error example
Cursor options cannot be changed after execution has started. Clone the cursor first if you need a variant.

AggregationCursor<TResult>

The aggregation cursor is similar, but it loads from fetchAll(...) instead of page-by-page find calls.

Supported public methods:

  • next()
  • tryNext()
  • hasNext()
  • toArray()
  • forEach()
  • map()
  • rewind()
  • clone()
  • close()

Common option types

FindOptions<TSchema>

interface FindOptions<TSchema> {
readonly limit?: number;
readonly skip?: number;
readonly projection?: Projection<TSchema>;
readonly sort?: Sort;
readonly cursor?: {
readonly token: string;
readonly direction: "next" | "previous";
};
}

UpdateOptions

interface UpdateOptions {
readonly idempotencyKey?: string;
readonly upsert?: boolean;
}

CursorOperationOptions

interface CursorOperationOptions {
readonly signal?: AbortSignal;
}

Use signal when you need cancellation in long-running query or aggregation flows.