[data-reveal]{opacity:1!important;transform:none!important}
Database

Filtering and Querying

This guide covers techniques for selecting, comparing, and transforming documents using AQL's filter and ValueProxy capabilities.
import { Schema } from "@antelopejs/interface-database";

const schema = Schema.get("myapp")!;
const users = schema.instance().table("users");

Basic Filtering

Use the filter method with a predicate function. The callback receives a ValueProxy<T> representing each document.

const active = await users.filter((user) =>
  user.key("status").eq("active"),
);

Comparison Operators

Equality and Inequality

const admins = await users.filter((u) => u.key("role").eq("admin"));
const nonAdmins = await users.filter((u) => u.key("role").ne("admin"));

Numeric Comparisons

const adults = await users.filter((u) => u.key("age").ge(18));
const seniors = await users.filter((u) => u.key("age").gt(65));
const young = await users.filter((u) => u.key("age").lt(18));
const discounted = await users.filter((u) => u.key("age").le(25));

Logical Operators

Combine conditions with and(), or(), and not():

// AND
const verified = await users.filter((u) =>
  u.key("status").eq("active").and(u.key("emailVerified").eq(true)),
);

// OR
const important = await users.filter((u) =>
  u.key("role").eq("admin").or(u.key("plan").eq("premium")),
);

// NOT
const standard = await users.filter((u) =>
  u.key("plan").eq("premium").not(),
);

// Complex combinations
const target = await users.filter((u) =>
  u.key("status").eq("active")
    .and(
      u.key("plan").eq("premium")
        .or(u.key("totalPurchases").gt(500)),
    ),
);

String Operations

// Case-insensitive match
const bobs = await users.filter((u) =>
  u.key("name").downcase().eq("bob"),
);

// Regex matching
const gmailUsers = await users.filter((u) =>
  u.key("email").match("@gmail\\.com$"),
);

// String concatenation in filter
const fullNameMatch = await users.filter((u) =>
  u.key("firstName").concat(u.key("lastName")).eq("JohnSmith"),
);

Date Filtering

Date Comparisons

const newUsers = await users.filter((u) =>
  u.key("createdAt").gt(new Date("2024-01-01")),
);

const q1Users = await users.filter((u) =>
  u.key("createdAt").ge(new Date("2024-01-01"))
    .and(u.key("createdAt").lt(new Date("2024-04-01"))),
);

Date Components

const thisYear = await users.filter((u) =>
  u.key("createdAt").year().eq(2024),
);

const morningLogins = await users.filter((u) =>
  u.key("lastLogin").hours().lt(12),
);

Array Operations

// Check array contents
const jsPosts = await schema.instance().table("posts").filter((post) =>
  post.key("tags").includes("javascript"),
);

// Check array length
const wellTagged = await schema.instance().table("posts").filter((post) =>
  post.key("tags").count().gt(3),
);

// Check if empty
const untagged = await schema.instance().table("posts").filter((post) =>
  post.key("tags").isempty(),
);

Default Values in Filters

Use default() to handle potentially null fields:

const activeUsers = await users.filter((u) =>
  u.key("active").default(false).eq(true),
);

const frequentVisitors = await users.filter((u) =>
  u.key("visits").default(0).gt(10),
);

Ordering and Pagination

// Sort ascending
const byName = await users.orderBy("name", "asc");

// Sort descending
const newest = await users.orderBy("createdAt", "desc");

// Paginate
const page1 = await users.orderBy("createdAt").slice(0, 10);
const page2 = await users.orderBy("createdAt").slice(10, 10);

Performance Tips

  1. Use getAll() and between() with indexes instead of filter() when possible. Index-based lookups are significantly faster than full scans.
  2. Filter early in the query chain to reduce the dataset before applying transformations or aggregations.
  3. Limit result sets with slice() to avoid transferring unnecessary data.
  4. Avoid complex computations inside filter predicates when simpler alternatives exist.
// Slower: full table scan with filter
const slow = await users.filter((u) => u.key("email").eq("[email protected]"));

// Faster: index-based lookup
const fast = await users.getAll("[email protected]", "email");