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

> Master complex where queries in JSON Server using the _where parameter. Learn to filter resources with precision using advanced field operators and logical conditions. Boost your API development today.

- Repository: [typicode/json-server](https://github.com/typicode/json-server)
- Tags: how-to-guide
- Published: 2026-03-01

---

**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`](https://github.com/typicode/json-server/blob/main/src/parse-where.ts) and [`src/matches-where.ts`](https://github.com/typicode/json-server/blob/main/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`](https://github.com/typicode/json-server/blob/main/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`](https://github.com/typicode/json-server/blob/main/src/matches-where.ts) file evaluates each resource against the parsed where object. It references the operator definitions in [`src/where-operators.ts`](https://github.com/typicode/json-server/blob/main/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:

```http
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:

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

```

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

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

```

### List Filters with `in`

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

```http
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":

```http
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:

```http
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`](https://github.com/typicode/json-server/blob/main/src/where-operators.ts) | Declares supported operators (`lt`, `gt`, `contains`, etc.) and type guards | [`src/where-operators.ts`](https://github.com/typicode/json-server/blob/main/src/where-operators.ts) |
| [`src/parse-where.ts`](https://github.com/typicode/json-server/blob/main/src/parse-where.ts) | Parses query strings into structured where objects, handles `in` array conversion | [`src/parse-where.ts`](https://github.com/typicode/json-server/blob/main/src/parse-where.ts) |
| [`src/matches-where.ts`](https://github.com/typicode/json-server/blob/main/src/matches-where.ts) | Evaluates resources against parsed where objects with recursive matching | [`src/matches-where.ts`](https://github.com/typicode/json-server/blob/main/src/matches-where.ts) |
| [`README.md`](https://github.com/typicode/json-server/blob/main/README.md) | User-facing documentation for the `_where` API | [`README.md`](https://github.com/typicode/json-server/blob/main/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`](https://github.com/typicode/json-server/blob/main/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`](https://github.com/typicode/json-server/blob/main/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`](https://github.com/typicode/json-server/blob/main/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`](https://github.com/typicode/json-server/blob/main/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.