Build your own vector database
Payload filtering (the Qdrant problem)·18 min

The filter predicate

0 / 1
# grade this stage (from your course directory)
npx theinference test --stage filter-predicate --watch

Before filtered search, the predicate it gates on. Implement matches(payload, filter) for a small Qdrant-like filter language: must (AND), should (OR), must_not (NONE), with leaf conditions match (equality), range (gte/lte), and is (boolean).

The filter shape
type Leaf =
  | { match: { key; value } }
  | { range: { key; gte?; lte? } }
  | { is:    { key; value: boolean } }

interface Filter { must?: Leaf[]; should?: Leaf[]; must_not?: Leaf[] }

What to build

Your task

Implement runMatches

Implement matches(payload, filter) in src/payload.ts. A payload satisfies the filter when all must leaves pass, none of the must_not leaves pass, and (if should is non-empty) at least one should leaf passes. Return a boolean; the adapter maps it to [1]/[0].

tests/adapters.ts
export function runMatches(payload: Payload, filter: Filter): number[] {
  // return [ matches(payload, filter) ? 1 : 0 ]
}
Keep it boolean-pure

This mirrors Qdrant's Filter object (must / should / must_not, match / range). The search layer calls it purely as an admission gate, so no side effects — just a clean boolean.

How it's graded

Adapter mode: [1]/[0] compared exactly to the reference for a fixed payload + compound filter (a must + range + must_not).