Skip to main content
OnchainDB provides two approaches for querying data:
  1. Query Builder (Main API) - Compose complex queries with full control over conditions, joins, aggregations, and selections
  2. Helper Methods - Pre-built convenience methods like findMany(), findUnique() for common operations

Helper Methods (Simple Queries)

// Query all records in a collection
const allPosts = await client.query({
  collection: 'posts'
});

// Query with filters
const alicePosts = await client.query({
  collection: 'posts',
  filters: { author: 'alice' }
});

// Pagination
const page1 = await client.query({
  collection: 'posts',
  limit: 10,
  offset: 0
});

Query Builder (Main API)

Use the fluent query builder for complex queries:
import { LogicalOperator } from '@onchaindb/sdk';

// Complex query with logical operators
const results = await client.queryBuilder()
  .collection('posts')
  .find(builder =>
    LogicalOperator.And([
      LogicalOperator.Condition(builder.field('published').equals(true)),
      LogicalOperator.Or([
        LogicalOperator.Condition(builder.field('category').equals('tech')),
        LogicalOperator.Condition(builder.field('tags').contains('blockchain'))
      ])
    ])
  )
  .select(selection =>
    selection.field('title').field('content').field('author')
  )
  .limit(20)
  .execute();

// Quick field queries
const activeUsers = await client.queryBuilder()
  .collection('users')
  .whereField('status').equals('active')
  .selectFields(['id', 'name', 'email'])
  .limit(50)
  .execute();

Field Condition Operators

The query builder supports 25+ field condition operators. Here’s how to use them across all SDKs:

Comparison Operators

.equals(value)              // Field equals value
.notEquals(value)           // Field does not equal value
.greaterThan(value)         // Field > value
.lessThan(value)            // Field < value
.greaterThanOrEqual(value)  // Field >= value
.lessThanOrEqual(value)     // Field <= value
.between(min, max)          // Field value between min and max

String Operators

.contains(value)                    // Field contains substring
.startsWith(value)                  // Field starts with string
.endsWith(value)                    // Field ends with string
.regExpMatches(pattern)             // Field matches regex pattern
.includesCaseInsensitive(value)     // Case-insensitive contains
.startsWithCaseInsensitive(value)   // Case-insensitive starts with
.endsWithCaseInsensitive(value)     // Case-insensitive ends with

Array Operators

.in(values)                 // Field value in array
.notIn(values)              // Field value not in array

Boolean & Existence Operators

.isTrue()                   // Field is true
.isFalse()                  // Field is false
.isNull()                   // Field is null
.isNotNull()                // Field is not null
.exists()                   // Field exists
.notExists()                // Field does not exist

IP Address Operators

.isLocalIp()                // IP is local
.isExternalIp()             // IP is external
.inCountry(code)            // IP in country
.cidr(range)                // IP in CIDR range

Usage Examples

const products = await client.queryBuilder()
  .collection('products')
  .whereField('productDisplayName')
  .includesCaseInsensitive('shirt')
  .limit(20)
  .execute();

Range Query

const affordableProducts = await client.queryBuilder()
  .collection('products')
  .whereField('price')
  .between(10, 100)
  .execute();

Boolean Check

const activeUsers = await client.queryBuilder()
  .collection('users')
  .whereField('active')
  .isTrue()
  .execute();

Complex Logical Operations (AND/OR/NOT)

import { LogicalOperator, FieldConditionBuilder } from '@onchaindb/sdk';

const response = await client.queryBuilder()
  .collection('users')
  .find(builder =>
    builder.orGroup(() => [
      // Admins or moderators
      LogicalOperator.And([
        LogicalOperator.Condition(
          new FieldConditionBuilder('role').in(['admin', 'moderator'])
        ),
        LogicalOperator.Condition(
          new FieldConditionBuilder('active').equals(true)
        )
      ]),
      // Premium users
      LogicalOperator.And([
        LogicalOperator.Condition(
          new FieldConditionBuilder('subscription').equals('premium')
        ),
        LogicalOperator.Condition(
          new FieldConditionBuilder('verified').equals(true)
        )
      ])
    ])
  )
  .execute();

executeUnique()

Returns the latest record by metadata timestamp (updatedAt or createdAt). Useful for finding a single record when multiple versions may exist:
const user = await client.queryBuilder()
  .collection('users')
  .whereField('email').equals('alice@example.com')
  .executeUnique<User>();
// Returns: User | null (latest version by timestamp)

Selection Builder

Control which fields are returned:
import { SelectionBuilder } from '@onchaindb/sdk';

// Select specific fields
const selection = new SelectionBuilder()
  .field('id')
  .field('name')
  .field('email')
  .build();

// Or using selectFields directly
const users = await client.queryBuilder()
  .collection('users')
  .selectFields(['id', 'name', 'email'])
  .execute();

// Nested field selection
const results = await client.queryBuilder()
  .collection('users')
  .select(s => s
    .field('id')
    .nested('profile', n => n.field('bio').field('avatar'))
  )
  .execute();

Sorting and Pagination

const users = await client.queryBuilder()
  .collection('users')
  .orderBy('createdAt', 'desc')
  .limit(10)
  .offset(20)
  .execute();

Next Steps