Skip to main content

Query & Filtering

Master advanced query techniques including filtering, searching, sorting, and pagination with powerful operators across all platforms.
Cocobase provides a comprehensive query system with support for complex filters, logical operators, and efficient pagination.

Overview

Build powerful queries with:
  • Comparison operators - Equal, not equal, greater than, less than
  • String operators - Contains, starts with, ends with, regex
  • List operators - In, not in
  • Logical operators - AND, OR, NOT combinations
  • Sorting - Order results by any field
  • Pagination - Limit and offset for large datasets
  • Query builder - Fluent, chainable API

Basic Filtering

Filter documents by field values with automatic type handling.

Equality Filters

import { Cocobase } from 'cocobase';

const db = new Cocobase({ apiKey: 'your-api-key' });

// Simple equality
const activeUsers = await db.listDocuments('users', {
  filters: { status: 'active' }
});

// Multiple filters (AND logic)
const specificUsers = await db.listDocuments('users', {
  filters: {
    status: 'active',
    role: 'admin',
    verified: true
  }
});

Query Operators

Comparison Operators

Filter by numeric ranges and comparisons.
// Greater than
const seniors = await db.listDocuments('users', {
  filters: { age_gt: 65 }
});

// Greater than or equal
const adults = await db.listDocuments('users', {
  filters: { age_gte: 18 }
});

// Less than
const minors = await db.listDocuments('users', {
  filters: { age_lt: 18 }
});

// Less than or equal
const eligible = await db.listDocuments('users', {
  filters: { age_lte: 65 }
});

// Not equal
const nonAdmins = await db.listDocuments('users', {
  filters: { role_ne: 'admin' }
});

// Between (range)
const midAge = await db.listDocuments('users', {
  filters: {
    age_gte: 25,
    age_lte: 40
  }
});

String Operators

Search and filter text fields with powerful string operations.
// Contains (case-insensitive)
const johns = await db.listDocuments('users', {
  filters: { name_contains: 'john' }
});

// Starts with
const admins = await db.listDocuments('users', {
  filters: { email_startswith: 'admin' }
});

// Ends with
const gmailUsers = await db.listDocuments('users', {
  filters: { email_endswith: '@gmail.com' }
});

// Multiple string filters
const specific = await db.listDocuments('users', {
  filters: {
    name_contains: 'john',
    email_endswith: '@example.com'
  }
});

List Operators

Filter by multiple possible values.
// In - match any of the values
const staff = await db.listDocuments('users', {
  filters: { role_in: 'admin,moderator,support' }
});

// Not in - exclude values
const active = await db.listDocuments('users', {
  filters: { status_notin: 'deleted,banned,suspended' }
});

// Array contains (for array fields)
const followers = await db.listDocuments('users', {
  filters: { 'followers_array_contains': 'user_123' }
});

Logical Operators

Combine filters with AND and OR logic for complex queries.

OR Queries

// Simple OR - match any condition
const users = await db.listDocuments('users', {
  filters: {
    '[or]role': 'admin',
    '[or]isPremium': true
  }
});

// Multi-field search
const searchResults = await db.listDocuments('users', {
  filters: {
    'name__or__email_contains': 'john'
  }
});

Complex Queries (AND + OR)

// Active users who are (admin OR moderator)
const users = await db.listDocuments('users', {
  filters: {
    status: 'active',
    '[or]role': 'admin',
    '[or]role': 'moderator'
  }
});

// Advanced: (Premium OR Verified) AND Active
const eligibleUsers = await db.listDocuments('users', {
  filters: {
    status: 'active',
    '[or:tier]isPremium': true,
    '[or:tier]isVerified': true
  }
});

Sorting

Order results by any field in ascending or descending order.
// Sort ascending
const byName = await db.listDocuments('users', {
  orderBy: 'name',
  order: 'asc'
});

// Sort descending
const newest = await db.listDocuments('users', {
  orderBy: 'created_at',
  order: 'desc'
});

// Multiple sorts
const sorted = await db.listDocuments('users', {
  orderBy: 'role,name',
  order: 'asc'
});

Pagination

Efficiently handle large datasets with limit and offset.
// Get first page (10 items)
const page1 = await db.listDocuments('users', {
  limit: 10,
  offset: 0
});

// Get next page
const page2 = await db.listDocuments('users', {
  limit: 10,
  offset: 10
});

// Helper function
async function getPage(pageNumber, pageSize = 10) {
  return db.listDocuments('users', {
    limit: pageSize,
    offset: (pageNumber - 1) * pageSize
  });
}

const page3 = await getPage(3);

Query Builder Pattern

Use fluent, chainable APIs for complex queries.
// Not directly supported in JS SDK - use filters object
const users = await db.listDocuments('users', {
  filters: {
    status: 'active',
    age_gte: 18,
    role_in: 'admin,moderator'
  },
  orderBy: 'created_at',
  order: 'desc',
  limit: 20
});

Real-World Examples

async function searchProducts(searchTerm, minPrice, maxPrice, category) {
  return await db.listDocuments('products', {
    filters: {
      name_contains: searchTerm,
      price_gte: minPrice,
      price_lte: maxPrice,
      category: category,
      inStock: true
    },
    orderBy: 'popularity',
    order: 'desc',
    limit: 24
  });
}

const laptops = await searchProducts('laptop', 500, 2000, 'electronics');

Social Feed with Filters

async function getUserFeed(userId, page = 1) {
  return await db.listDocuments('posts', {
    filters: {
      '[or]author_id': userId,
      '[or]followers_array_contains': userId,
      status: 'published'
    },
    orderBy: 'created_at',
    order: 'desc',
    limit: 20,
    offset: (page - 1) * 20
  });
}

const myFeed = await getUserFeed('user-123');

Best Practices

Filter on the server, not the client. This reduces bandwidth and improves performance.
// ✓ Good: Filter on server
const users = await db.listDocuments('users', {
  filters: { status: 'active', age_gte: 18 }
});

// ✗ Bad: Fetch all, filter client-side
const allUsers = await db.listDocuments('users');
const filtered = allUsers.filter(u => u.status === 'active' && u.age >= 18);
Never fetch all documents at once. Use limit and offset for better performance.
// ✓ Good: Paginated
const users = await db.listDocuments('users', {
  limit: 50,
  offset: 0
});

// ✗ Bad: No limit
const allUsers = await db.listDocuments('users');
Contact support to add indexes for fields you query often for better performance.
Order filters from most to least selective for optimal query planning.
// ✓ Good: Most selective first
filters: {
  id: 'specific-id',        // Very selective
  email: '[email protected]', // Selective
  status: 'active'          // Less selective
}
For complex queries with OR logic, use the query builder pattern.
// ✓ Good: Clear structure
final users = await db.listDocuments('users',
  queryBuilder: QueryBuilder()
    .where('status', 'active')
    .or()
      .where('isPremium', true)
      .where('isVerified', true)
    .done()
    .recent()
);

Operator Reference

Comparison Operators

OperatorSuffixDescriptionExample
Equal(none)Exact matchstatus=active
Not Equal_neNot equal torole_ne=admin
Greater_gtGreater thanage_gt=18
Gte_gteGreater than or equalage_gte=18
Less_ltLess thanage_lt=65
Lte_lteLess than or equalage_lte=65

String Operators

OperatorSuffixDescriptionExample
Contains_containsSubstringname_contains=john
Starts_startswithStarts withemail_startswith=admin
Ends_endswithEnds with[email protected]

List Operators

OperatorSuffixDescriptionExample
In_inMatch anyrole_in=admin,moderator
Not In_notinExclude valuesstatus_notin=deleted,banned
Contains_array_containsArray containstags_array_contains=featured

Next Steps