How to Use Complex Where Queries with the _where Parameter in JSON Server

JSON Server supports advanced filtering through the _where query parameter, which accepts a JSON object defining field-level operators like gt, lt, contains, and logical or conditions to filter resources with precision.

The _where parameter transforms JSON Server from a simple REST mock into a queryable database backend. By leveraging the implementation found in src/parse-where.ts and src/matches-where.ts, you can construct complex filter expressions that handle numeric ranges, string patterns, list membership, and nested logical operations.

How the _where Parameter Works

When you append ?_where= to a JSON Server endpoint, the engine processes your request through three distinct phases:

Step 1: Parsing the Query String

The src/parse-where.ts module splits each key in the _where JSON into a path and an operator. For example, views:gt becomes the path views with operator gt, while name_lt is parsed as path name with operator lt. The parser also coerces values to appropriate types (numbers, booleans, or strings) based on the context.

Step 2: Building the Where Object

Using the internal setPathOp function, JSON Server constructs a nested "where" object where operators become sub-properties of their respective fields. For instance, {views:{gt:100}} represents "views greater than 100". This function specifically handles the in operator by converting comma-separated strings into arrays for list-based filtering.

Step 3: Matching Records

The src/matches-where.ts file evaluates each resource against the parsed where object. It references the operator definitions in src/where-operators.ts (which includes lt, lte, gt, gte, eq, ne, in, contains, startsWith, endsWith, and or) and applies them with short-circuit logic. If a field contains an object, the matcher recurses, enabling deep nesting for complex document structures.

Supported Operators

JSON Server recognizes the following operators within _where query objects:

Operator Meaning Example Usage
lt / lte Less than / Less than or equal price:lt=10
gt / gte Greater than / Greater than or equal views:gt=100
eq / ne Equal / Not equal status:eq=active
in Value exists in list (comma-separated) category:in=books,movies
contains Substring match (case-insensitive) title:contains=react
startsWith / endsWith Prefix / Suffix match name:startsWith=Al
or Logical OR of multiple conditions {"or":[{"views":{"gt":1000}},{"published":{"eq":false}}]}

Practical Examples

Basic Numeric Filters

Filter posts with more than 100 views using the gt operator:

GET /posts?_where={"views":{"gt":100}}

This parses to { views: { gt: 100 } } and returns only records where the views field exceeds 100.

String Operators

Search for posts containing "json" anywhere in the title:

GET /posts?_where={"title":{"contains":"json"}}

Match authors whose names start with "A" using nested object notation:

GET /posts?_where={"author":{"name":{"startsWith":"A"}}}

List Filters with in

Retrieve posts in specific categories by providing a comma-separated list:

GET /posts?_where={"category":{"in":"news,sports"}}

The parser converts the string "news,sports" into an array ["news", "sports"] for the in operator evaluation.

Logical OR Queries

Combine conditions where posts either have high view counts OR author names alphabetically before "m":

GET /posts?_where={"or":[{"views":{"gt":1000}},{"author":{"name":{"lt":"m"}}}]}

The or operator accepts an array of filter objects, matching records that satisfy at least one condition.

Nested and Compound Filters

Filter for posts with authors aged 30 or older whose names contain "smith", where the post is also published:

GET /posts?_where={"author":{"age":{"gte":30},"name":{"contains":"smith"}},"published":true}

This demonstrates deep nesting (author object with multiple fields) combined with top-level boolean fields.

Key Implementation Files

Understanding these source files helps debug complex queries and extend functionality:

File Role Location
src/where-operators.ts Declares supported operators (lt, gt, contains, etc.) and type guards src/where-operators.ts
src/parse-where.ts Parses query strings into structured where objects, handles in array conversion src/parse-where.ts
src/matches-where.ts Evaluates resources against parsed where objects with recursive matching src/matches-where.ts
README.md User-facing documentation for the _where API README.md

These modules work sequentially: parsing converts HTTP parameters to JavaScript objects, then matching applies operator logic against your JSON database records.

Summary

  • The _where parameter accepts a JSON object defining field operators for advanced filtering in JSON Server.
  • Supported operators include comparison (gt, lt, gte, lte), equality (eq, ne), string matching (contains, startsWith, endsWith), list membership (in), and logical disjunction (or).
  • Query parsing happens in src/parse-where.ts, which splits field operators and handles array conversion for the in operator.
  • Record matching is performed by src/matches-where.ts, which recursively evaluates nested objects and applies short-circuit logic for or conditions.
  • When present, _where overrides other query parameters like sorting and pagination.

Frequently Asked Questions

How do I filter for values within a specific range using _where?

Combine the gte (greater than or equal) and lte (less than or equal) operators in a single query object. For example, to find posts with views between 100 and 500, use ?_where={"views":{"gte":100,"lte":500}}. JSON Server evaluates both conditions as an implicit AND operation, returning only records that satisfy the range.

Can I use _where to search nested JSON objects?

Yes, the matcher in src/matches-where.ts recursively traverses nested objects. Use dot-path notation or nested JSON structures to target deep fields. For example, ?_where={"author":{"profile":{"age":{"gt":25}}}} filters posts where author.profile.age exceeds 25. The parser handles the nested structure, and the matcher evaluates each level sequentially.

What happens if I combine _where with other query parameters like _sort or _page?

According to the JSON Server source code and README, when _where is present in the query string, it takes precedence and overrides standard filtering, sorting, and pagination parameters. The server processes the complex filter first, then applies any remaining parameters only if they do not conflict with the _where constraints. For predictable results, place all filter logic within the _where JSON object rather than mixing syntaxes.

Why does my _where query return an empty array when I expect results?

This typically occurs due to type mismatches or incorrect operator syntax. The parser in src/parse-where.ts coerces values based on context, but comparing strings to numbers or using unsupported operators causes silent failures. Verify that your JSON is valid, operators are spelled correctly (gt not greaterThan), and field names match your database schema exactly. Check the server logs for parsing errors that indicate which part of the _where object failed validation.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →