# Catalog API

The Catalog API (`list.catalog`) provides powerful querying, filtering, and analytical functions for working with data in a list. It's the primary interface for retrieving and analyzing data.

## Overview

Each list has its own catalog instance that maintains independent query state and provides access to:

- **Query operations**: Apply, execute, and manage filters
- **Analytical functions**: Facets, aggregations, pivot tables, grouping, suggestions
- **Data retrieval**: Get items with projection and sorting

The examples on this page run against this setup (load your data with `dcupl.data.set()` before `init()`):

```typescript title="Setup used by the examples"
import { Dcupl } from '@dcupl/core';

const dcupl = new Dcupl();
dcupl.models.set({
  key: 'Manufacturer',
  properties: [
    { key: 'name', type: 'string' },
    { key: 'country', type: 'string' },
  ],
});
dcupl.models.set({
  key: 'Category',
  properties: [{ key: 'name', type: 'string' }],
  references: [
    { key: 'parent', type: 'singleValued', model: 'Category' },
    { key: 'manufacturer', type: 'singleValued', model: 'Manufacturer' },
  ],
});
dcupl.models.set({
  key: 'Product',
  properties: [
    { key: 'name', type: 'string' },
    { key: 'price', type: 'float' },
    { key: 'quantity', type: 'int' },
    { key: 'rating', type: 'float' },
    { key: 'status', type: 'string' },
    { key: 'featured', type: 'boolean' },
    { key: 'createdAt', type: 'date' },
    { key: 'tags', type: 'Array<string>' },
  ],
  references: [
    { key: 'category', type: 'singleValued', model: 'Category' },
    { key: 'manufacturer', type: 'singleValued', model: 'Manufacturer' },
  ],
});
await dcupl.init();

const list = dcupl.lists.create({ modelKey: 'Product' });
```

## API namespaces

### catalog.query

Main query interface for filtering and retrieving data.

**See:** [Query Operations](#query-operations)

### catalog.fn

Analytical functions for data analysis.

**See:** [Analytical Functions](#analytical-functions)

### catalog.filters

Filter items for building filter UIs: `filters.getAll()` and `filters.get({ filterKey })` return one item per attribute marked `filter: true` in the model (facet `entries` for references and booleans, a `range` for numbers and dates, only a `comparisonType` for text). For facet counts of any attribute, use [`fn.facets()`](/sdk/fn/facets).

## Query operations

In the signatures below, `Item` is the type you give [`dcupl.lists.create<Item>()`](/sdk/api/lists#create), with `key: string` added; without a type argument it is `any`. `one()` and `many()` take no type argument and return `Item`. The other reads take an optional type argument that must extend `Item`, for example `items<ProductWithStock>()`; the options you pass never change the returned type.

### addCondition()

Adds query condition(s) to the catalog. Use this to filter data.

Each condition goes into the group keyed by its attribute (created as an `'or'` group if missing). Conditions on **different** attributes are therefore combined with AND, conditions on the **same** attribute with OR. For a range on one attribute (`price >= 50` AND `price <= 200`), use [`addGroup()`](#addgroup) with `groupType: 'and'`.

**Signature:**

```typescript
addCondition(
  condition: DcuplQuery | DcuplQuery[],
  options?: { skipProcessing?: boolean }
): DcuplGlobalQueryOptions
```

**Parameters:**

| Parameter                | Type                         | Required | Description                     |
| ------------------------ | ---------------------------- | -------- | ------------------------------- |
| `condition`              | `DcuplQuery \| DcuplQuery[]` | Yes      | Query condition(s) to add       |
| `options.skipProcessing` | `boolean`                    | No       | Skip immediate query processing |

**Returns:** `DcuplGlobalQueryOptions` - Current query state

**Examples:**

```typescript title="Add single condition"
list.catalog.query.addCondition({
  operator: 'eq',
  attribute: 'status',
  value: 'active',
});
```

```typescript title="Add multiple conditions"
list.catalog.query.addCondition([
  { operator: 'eq', attribute: 'status', value: 'active' },
  { operator: 'gte', attribute: 'price', value: 100 },
]);
// status = 'active' AND price >= 100
```

```typescript title="Same attribute: OR"
list.catalog.query.addCondition([
  { operator: 'eq', attribute: 'category', value: { key: 'electronics' } },
  { operator: 'eq', attribute: 'category', value: { key: 'books' } },
]);
// category = electronics OR category = books
```

```typescript title="Add condition with a query key"
list.catalog.query.addCondition({
  operator: 'eq',
  attribute: 'category',
  value: { key: 'electronics' },
  queryKey: 'categoryFilter',
});

list.catalog.query.has({ groupKey: 'category', queryKey: 'categoryFilter' }); // true
```

### setCondition()

Replaces the conditions on the condition's attribute (the group keyed by that attribute) with the new condition(s). Groups for other attributes are kept. To replace the whole query, call [`clear()`](#clear) first or use [`apply()`](#apply) with the root group.

**Signature:**

```typescript
setCondition(
  condition: DcuplQuery | DcuplQuery[],
  options?: { skipProcessing?: boolean }
): DcuplGlobalQueryOptions
```

**Parameters:**

| Parameter                | Type                         | Required | Description                     |
| ------------------------ | ---------------------------- | -------- | ------------------------------- |
| `condition`              | `DcuplQuery \| DcuplQuery[]` | Yes      | Query condition(s) to set       |
| `options.skipProcessing` | `boolean`                    | No       | Skip immediate query processing |

**Returns:** `DcuplGlobalQueryOptions` - Current query state

**Examples:**

```typescript title="Replace the status condition"
list.catalog.query.addCondition({ operator: 'eq', attribute: 'featured', value: true });
list.catalog.query.addCondition({ operator: 'eq', attribute: 'status', value: 'active' });

list.catalog.query.setCondition({
  operator: 'eq',
  attribute: 'status',
  value: 'inactive',
});
// featured = true AND status = 'inactive'
```

```typescript title="Replace several attributes at once"
list.catalog.query.setCondition([
  { operator: 'eq', attribute: 'status', value: 'active' },
  { operator: 'gte', attribute: 'price', value: 100 },
]);
```

### addGroup()

Adds a query group with multiple conditions combined by AND/OR logic.

- A group **with** a `groupKey` extends the existing group with that key (its `groupType` is replaced if you pass one) or is created.
- A group **without** a `groupKey` is always appended as a new group.
- A newly created group without `groupType` is stored as `'or'`. Always set `groupType` explicitly.

**Signature:**

```typescript
addGroup(
  group: DcuplQueryGroup,
  options?: { skipProcessing?: boolean }
): DcuplGlobalQueryOptions
```

**Parameters:**

| Parameter                | Type              | Required | Description                     |
| ------------------------ | ----------------- | -------- | ------------------------------- |
| `group`                  | `DcuplQueryGroup` | Yes      | Query group to add              |
| `options.skipProcessing` | `boolean`         | No       | Skip immediate query processing |

**Returns:** `DcuplGlobalQueryOptions` - Current query state

**Examples:**

```typescript title="Add price range group (AND logic)"
list.catalog.query.addGroup({
  groupKey: 'priceRange',
  groupType: 'and',
  queries: [
    { operator: 'gte', attribute: 'price', value: 50 },
    { operator: 'lte', attribute: 'price', value: 200 },
  ],
});
```

```typescript title="Add category group (OR logic)"
list.catalog.query.addGroup({
  groupKey: 'categories',
  groupType: 'or',
  queries: [
    { operator: 'eq', attribute: 'category', value: { key: 'electronics' } },
    { operator: 'eq', attribute: 'category', value: { key: 'books' } },
  ],
});
```

### setGroup()

Replaces the group with the same `groupKey`, found at any depth (a top-level match wins); all other groups and the item options are kept. A group given without `groupType` is stored as `'or'`. A group without `groupKey` replaces the first top-level group that has no `groupKey`; it is only appended when there is none. Give groups a `groupKey` so you know which one `setGroup()` replaces.

**Signature:**

```typescript
setGroup(
  group: DcuplQueryGroup,
  options?: { skipProcessing?: boolean }
): DcuplGlobalQueryOptions
```

**Example:**

```typescript title="Change the price range"
list.catalog.query.setGroup({
  groupKey: 'priceRange',
  groupType: 'and',
  queries: [
    { operator: 'gte', attribute: 'price', value: 100 },
    { operator: 'lte', attribute: 'price', value: 600 },
  ],
});
```

### items()

Executes the current query and returns matching items.

**Signature:**

```typescript
items<T extends Item = Item>(options?: DcuplListQueryOptions<NoInfer<T>>): T[]
```

**Parameters:**

| Parameter | Type                       | Required | Description             |
| --------- | -------------------------- | -------- | ----------------------- |
| `options` | `DcuplListQueryOptions<T>` | No       | Query execution options |

**Returns:** `T[]` - Array of matching items

Without `options`, the list's query and its applied item options (`start`, `count`, `sort`, `projection` from [`applyOptions()`](#applyoptions)) are used. Item options you pass override the applied ones for this call. `queries` you pass are applied on top of the list's query; in that case the applied item options are not used.

**Examples:**

```typescript title="Get all matching items"
const items = list.catalog.query.items();
```

```typescript title="With pagination"
const page = list.catalog.query.items({
  start: 0,
  count: 20,
});
```

```typescript title="With sorting"
const sorted = list.catalog.query.items({
  sort: { attributes: ['price', 'name'], order: ['DESC', 'ASC'] },
});
```

```typescript title="With projection"
const projected = list.catalog.query.items({
  projection: {
    name: true,
    price: true,
    category: true,
  },
});
```

```typescript title="Complete query execution"
const results = list.catalog.query.items({
  queries: [{ operator: 'eq', attribute: 'status', value: 'active' }],
  start: 0,
  count: 20,
  sort: { attributes: ['price', 'name'], order: ['DESC', 'ASC'] },
  projection: { name: true, price: true },
});
```

### first()

Returns the first matching item.

**Signature:**

```typescript
first<T extends Item = Item>(options?: DcuplListQueryOptions<NoInfer<T>>): T | undefined
```

**Parameters:**

| Parameter | Type                       | Required | Description             |
| --------- | -------------------------- | -------- | ----------------------- |
| `options` | `DcuplListQueryOptions<T>` | No       | Query execution options |

**Returns:** `T | undefined` - First matching item or undefined

**Examples:**

```typescript title="Get first item"
const item = list.catalog.query.first();
```

```typescript title="First matching condition"
const activeItem = list.catalog.query.first({
  queries: [{ operator: 'eq', attribute: 'status', value: 'active' }],
});
```

### count()

Returns the count of matching items.

**Signature:**

```typescript
count<T extends Item = Item>(options?: DcuplListQueryOptions<NoInfer<T>>): number
```

**Parameters:**

| Parameter | Type                       | Required | Description             |
| --------- | -------------------------- | -------- | ----------------------- |
| `options` | `DcuplListQueryOptions<T>` | No       | Query execution options |

**Returns:** `number` - Count of matching items

`count()` returns the length of [`items()`](#items) for the same options, so it respects an applied `start`/`count` (the size of the current page). The total number of matches is `list.catalog.fn.metadata().currentSize`.

**Examples:**

```typescript title="Count the current result"
const pageSize = list.catalog.query.count();
const total = list.catalog.fn.metadata().currentSize;
```

```typescript title="Count matching condition"
const activeCount = list.catalog.query.count({
  queries: [{ operator: 'eq', attribute: 'status', value: 'active' }],
});
```

### any()

Checks if any results exist.

**Signature:**

```typescript
any<T extends Item = Item>(options?: DcuplListQueryOptions<NoInfer<T>>): boolean
```

**Parameters:**

| Parameter | Type                       | Required | Description             |
| --------- | -------------------------- | -------- | ----------------------- |
| `options` | `DcuplListQueryOptions<T>` | No       | Query execution options |

**Returns:** `boolean` - True if any results exist

**Examples:**

```typescript title="Check if any items exist"
if (list.catalog.query.any()) {
  console.log('Items found');
}
```

```typescript title="Check for specific condition"
const hasActive = list.catalog.query.any({
  queries: [{ operator: 'eq', attribute: 'status', value: 'active' }],
});
```

### removeCondition()

Removes specific query condition(s). Pass each condition as you added it (`attribute`, `operator`, `value`); it is removed from the group keyed by its attribute, and a group left empty is removed too. To remove every condition on one attribute, use [`removeGroup()`](#removegroup) with the attribute name.

**Signature:**

```typescript
removeCondition(
  condition: DcuplQuery | DcuplQuery[],
  options?: { skipProcessing?: boolean }
): DcuplGlobalQueryOptions
```

**Parameters:**

| Parameter                | Type                         | Required | Description                     |
| ------------------------ | ---------------------------- | -------- | ------------------------------- |
| `condition`              | `DcuplQuery \| DcuplQuery[]` | Yes      | Condition(s) to remove          |
| `options.skipProcessing` | `boolean`                    | No       | Skip immediate query processing |

**Returns:** `DcuplGlobalQueryOptions` - Updated query state

**Examples:**

```typescript title="Remove a condition"
list.catalog.query.removeCondition({
  operator: 'eq',
  attribute: 'status',
  value: 'active',
});
```

```typescript title="Remove all conditions on an attribute"
list.catalog.query.removeGroup('status');
```

```typescript title="Remove multiple"
list.catalog.query.removeCondition([
  { operator: 'eq', attribute: 'status', value: 'active' },
  { operator: 'eq', attribute: 'category', value: { key: 'electronics' } },
]);
```

### removeGroup()

Removes a query group by its key. Conditions added with `addCondition()` live in a group keyed by their attribute, so `removeGroup('price')` removes every condition on `price`.

**Signature:**

```typescript
removeGroup(
  groupKey: string,
  options?: { skipProcessing?: boolean }
): DcuplGlobalQueryOptions
```

**Parameters:**

| Parameter                | Type      | Required | Description                     |
| ------------------------ | --------- | -------- | ------------------------------- |
| `groupKey`               | `string`  | Yes      | Key of the group to remove      |
| `options.skipProcessing` | `boolean` | No       | Skip immediate query processing |

**Returns:** `DcuplGlobalQueryOptions` - Updated query state

**Examples:**

```typescript title="Remove price range group"
list.catalog.query.removeGroup('priceRange');
```

### clear()

Removes all query conditions and the item options (`start`, `count`, `sort`, `projection`).

**Signature:**

```typescript
clear(options?: { skipProcessing?: boolean }): DcuplGlobalQueryOptions
```

**Parameters:**

| Parameter                | Type      | Required | Description                     |
| ------------------------ | --------- | -------- | ------------------------------- |
| `options.skipProcessing` | `boolean` | No       | Skip immediate query processing |

**Returns:** `DcuplGlobalQueryOptions` - Empty query state (`{ modelKey, groupKey: 'root', groupType: 'and', queries: [] }`)

**Examples:**

```typescript title="Clear all filters"
list.catalog.query.clear();
```

```typescript title="Clear without processing"
list.catalog.query.clear({ skipProcessing: true });
```

```typescript title="Clear and get all items"
list.catalog.query.clear();
const allItems = list.catalog.query.items();
```

### current()

Returns the current query state.

**Signature:**

```typescript
current(): DcuplGlobalQueryOptions
```

**Returns:** `DcuplGlobalQueryOptions` - Current query configuration

**Examples:**

```typescript title="Get current query"
const query = list.catalog.query.current();
console.log(query.queries);
console.log(query.groupType);
```

```typescript title="Save query state"
const savedQuery = list.catalog.query.current();
```

```typescript title="Restore query state later"
// savedQuery is the root group (groupKey: 'root'), so 'set' replaces the whole query and its options
list.catalog.query.apply(savedQuery, { mode: 'set' });
```

### isEmpty()

Checks if the query has any conditions.

**Signature:**

```typescript
isEmpty(): boolean
```

**Returns:** `boolean` - True if no conditions are applied

**Examples:**

```typescript
if (list.catalog.query.isEmpty()) {
  console.log('No filters applied');
}
```

### has()

Checks if a specific query or group exists.

**Signature:**

```typescript
has(options: { groupKey: string; queryKey?: string }): boolean
```

**Parameters:**

| Parameter          | Type     | Required | Description                     |
| ------------------ | -------- | -------- | ------------------------------- |
| `options.groupKey` | `string` | Yes      | Group key to check              |
| `options.queryKey` | `string` | No       | Optional query key within group |

**Returns:** `boolean` - True if exists

`has()` finds a keyed group at any depth (a top-level match wins), also when a `queryKey` is given, like `removeGroup()`, `setGroup()` and `fn.facets({ excludeGroup })`.

**Examples:**

```typescript title="Check if group exists"
if (list.catalog.query.has({ groupKey: 'priceRange' })) {
  console.log('Price range filter is active');
}
```

```typescript title="Check if specific query exists"
// addCondition() puts the condition into the group keyed by its attribute
list.catalog.query.addCondition({ operator: 'eq', attribute: 'status', value: 'active', queryKey: 'statusFilter' });

if (
  list.catalog.query.has({
    groupKey: 'status',
    queryKey: 'statusFilter',
  })
) {
  console.log('Status filter is active');
}
```

### applyOptions()

Applies item options (pagination, sorting, projection) to the query state. This method sets or updates the non-filter options that affect how results are retrieved.

**Signature:**

```typescript
applyOptions(
  itemOptions: DcuplItemsOptions,
  options?: { mode?: 'set' | 'update'; skipProcessing?: boolean }
): DcuplGlobalQueryOptions
```

**Parameters:**

| Parameter                | Type                | Required | Description                                                                         |
| ------------------------ | ------------------- | -------- | ----------------------------------------------------------------------------------- |
| `itemOptions`            | `DcuplItemsOptions` | Yes      | Item options including start, count, projection, and sort                           |
| `options.mode`           | `'set' \| 'update'` | No       | `'set'` replaces all options, `'update'` merges with existing (default: `'update'`) |
| `options.skipProcessing` | `boolean`           | No       | Skip immediate query processing                                                     |

**DcuplItemsOptions:**

| Property     | Type                   | Description                   |
| ------------ | ---------------------- | ----------------------------- |
| `start`      | `number`               | Starting index for pagination |
| `count`      | `number`               | Number of items to return     |
| `projection` | `Projection<T>`        | Fields to include in results  |
| `sort`       | `SortingProjection<T>` | Sorting configuration         |

`sort` takes `{ attributes: [...], order: [...] }` with one `'ASC'` or `'DESC'` per attribute (uppercase). A `sort` with any other `order` value, or with not exactly one `order` entry per attribute, is ignored as a whole with a warning naming the expected shape, and the items keep their unsorted order. `projection` is an object of attribute names (`{ name: true, price: true }`); the item `key` is always included.

**Returns:** `DcuplGlobalQueryOptions` - Updated query state

**Examples:**

```typescript title="Set pagination"
list.catalog.query.applyOptions({
  start: 0,
  count: 20,
});
```

```typescript title="Set sorting"
list.catalog.query.applyOptions({
  sort: { attributes: ['price', 'name'], order: ['DESC', 'ASC'] },
});
```

```typescript title="Set projection"
list.catalog.query.applyOptions({
  projection: {
    name: true,
    price: true,
    category: true,
  },
});
```

```typescript title="Complete options"
list.catalog.query.applyOptions({
  start: 0,
  count: 20,
  sort: { attributes: ['price'], order: ['DESC'] },
  projection: { name: true, price: true, category: true },
});
```

```typescript title="Update existing options (merge)"
// First set initial options
list.catalog.query.applyOptions({
  start: 0,
  count: 20,
});

// Later, update only the sorting (keeps start and count)
list.catalog.query.applyOptions({ sort: { attributes: ['price'], order: ['DESC'] } }, { mode: 'update' });
```

```typescript title="Replace all options"
// Set new options, clearing any previously set options
list.catalog.query.applyOptions({ count: 50 }, { mode: 'set' });
```

```typescript title="Batch operations with skipProcessing"
// Apply multiple changes without intermediate processing
list.catalog.query.addCondition({ operator: 'eq', attribute: 'status', value: 'active' }, { skipProcessing: true });
list.catalog.query.applyOptions({
  start: 0,
  count: 20,
  sort: { attributes: ['createdAt'], order: ['DESC'] },
});
// Processing happens on the final call
```

With `skipProcessing: true` the query state changes, but the list's result is not recomputed and no `result_updated` event fires. Until a later call without it, `items()` and `count()` evaluate the new query on the previous result: an added condition already narrows it, but a removed condition or group (or `reset()`) does not widen it. `fn.facets()` counts the new query against the list's unfiltered data, while `one()`, `many()`, `fn.metadata()`, `fn.aggregate()`, `fn.groupBy()`, `fn.pivot()` and `fn.suggest()` still work on the previous result.

### one()

Returns a single item by key, if it is part of the list's current result.

**Signature:**

```typescript
one(options: DcuplItemOptions<Item>): Item | null
```

**Parameters:**

| Parameter | Type                     | Required | Description            |
| --------- | ------------------------ | -------- | ---------------------- |
| `options` | `DcuplItemOptions<Item>` | Yes      | Item retrieval options |

**Returns:** `Item | null` - The item, or `null` if the key is not in the list's current result

**Examples:**

```typescript title="Get item by key"
const item = list.catalog.query.one({ itemKey: 'p1' });
```

```typescript title="With projection"
const item = list.catalog.query.one({
  itemKey: 'p1',
  projection: { name: true, price: true },
});
```

### many()

Returns multiple specific items by keys. Keys that are not in the list's current result are skipped.

**Signature:**

```typescript
many(options: DcuplManyItemsOptions<Item>): Item[]
```

**Parameters:**

| Parameter | Type                          | Required | Description             |
| --------- | ----------------------------- | -------- | ----------------------- |
| `options` | `DcuplManyItemsOptions<Item>` | Yes      | Items retrieval options |

**Returns:** `Item[]` - Array of items

**Examples:**

```typescript title="Get specific items"
const items = list.catalog.query.many({
  itemKeys: ['p1', 'p2', 'p3'],
});
```

```typescript title="With projection"
const items = list.catalog.query.many({
  itemKeys: ['p1', 'p2', 'p3'],
  projection: { name: true, price: true },
});
```

## Core query methods

These are the foundational query methods. The semantic aliases (like `addCondition`, `clear`, `items`) provide a more intuitive API built on top of these core methods.

### apply()

Applies query condition(s) to the catalog. This is the core method that `addCondition()`, `setCondition()`, and `addGroup()` are built on.

**Signature:**

```typescript
apply(
  query: DcuplQueryGroup | DcuplQuery | DcuplQuery[] | DcuplQueryGroup[],
  options?: { mode?: 'set' | 'add'; skipProcessing?: boolean }
): DcuplGlobalQueryOptions
```

**Parameters:**

| Parameter                | Type                                                                 | Required | Description                                                                                    |
| ------------------------ | -------------------------------------------------------------------- | -------- | ---------------------------------------------------------------------------------------------- |
| `query`                  | `DcuplQueryGroup \| DcuplQuery \| DcuplQuery[] \| DcuplQueryGroup[]` | Yes      | Query condition(s) or group(s) to apply                                                        |
| `options.mode`           | `'set' \| 'add'`                                                     | No       | `'add'` (default) adds like `addCondition()`/`addGroup()`; `'set'` works per group (see below) |
| `options.skipProcessing` | `boolean`                                                            | No       | Skip immediate query processing                                                                |

**Returns:** `DcuplGlobalQueryOptions` - Updated query state

In `'set'` mode a condition replaces the conditions of its attribute group (like `setCondition()`) and a keyed group replaces the group with that key at any depth (like `setGroup()`); other groups are kept. A group without `groupKey` replaces the first top-level group without a key (appended if there is none). Only the root group (`groupKey: 'root'`) replaces the whole query, including its item options.

**Examples:**

```typescript title="Add a condition"
list.catalog.query.apply({ operator: 'eq', attribute: 'status', value: 'active' }, { mode: 'add' });
```

```typescript title="Replace the conditions on one attribute"
list.catalog.query.apply({ operator: 'eq', attribute: 'status', value: 'active' }, { mode: 'set' });
```

```typescript title="Replace the whole query"
list.catalog.query.apply(
  {
    groupKey: 'root',
    groupType: 'and',
    queries: [{ operator: 'eq', attribute: 'status', value: 'active' }],
  },
  { mode: 'set' },
);
```

```typescript title="Apply multiple conditions"
list.catalog.query.apply(
  [
    { operator: 'eq', attribute: 'status', value: 'active' },
    { operator: 'gte', attribute: 'price', value: 100 },
  ],
  { mode: 'add' },
);
```

```typescript title="Apply a query group"
list.catalog.query.apply(
  {
    groupKey: 'priceRange',
    groupType: 'and',
    queries: [
      { operator: 'gte', attribute: 'price', value: 50 },
      { operator: 'lte', attribute: 'price', value: 200 },
    ],
  },
  { mode: 'add' },
);
```

### remove()

Removes query condition(s) or groups from the catalog. This is the core method that `removeCondition()` and `removeGroup()` are built on.

**Signature:**

```typescript
remove(options?: Partial<DcuplQueryGroup> | DcuplQuery): DcuplGlobalQueryOptions
```

**Parameters:**

| Parameter | Type                                     | Required | Description                                                                               |
| --------- | ---------------------------------------- | -------- | ----------------------------------------------------------------------------------------- |
| `options` | `Partial<DcuplQueryGroup> \| DcuplQuery` | No       | Condition or group to remove. If omitted, removes all conditions (item options are kept). |

**Returns:** `DcuplGlobalQueryOptions` - Updated query state

**Examples:**

```typescript title="Remove a condition"
list.catalog.query.remove({ operator: 'eq', attribute: 'status', value: 'active' });
```

```typescript title="Remove by group key"
list.catalog.query.remove({ groupKey: 'priceRange' });
```

```typescript title="Remove all conditions"
list.catalog.query.remove();
```

### reset()

Resets the query to its initial empty state, including the item options. This is the core method that `clear()` wraps.

**Signature:**

```typescript
reset(options?: { skipProcessing?: boolean }): DcuplGlobalQueryOptions
```

**Parameters:**

| Parameter                | Type      | Required | Description                     |
| ------------------------ | --------- | -------- | ------------------------------- |
| `options.skipProcessing` | `boolean` | No       | Skip immediate query processing |

**Returns:** `DcuplGlobalQueryOptions` - Empty query state

**Examples:**

```typescript title="Reset query"
list.catalog.query.reset();
```

```typescript title="Reset without processing"
list.catalog.query.reset({ skipProcessing: true });
```

### execute()

Executes the current query and returns matching items. This is the core method that `items()` wraps.

**Signature:**

```typescript
execute<T extends Item = Item>(options?: DcuplListQueryOptions<NoInfer<T>>): T[]
```

**Parameters:**

| Parameter | Type                       | Required | Description             |
| --------- | -------------------------- | -------- | ----------------------- |
| `options` | `DcuplListQueryOptions<T>` | No       | Query execution options |

**Returns:** `T[]` - Array of matching items

**Examples:**

```typescript title="Execute current query"
const items = list.catalog.query.execute();
```

```typescript title="Execute with options"
const items = list.catalog.query.execute({
  start: 0,
  count: 20,
  sort: { attributes: ['price'], order: ['DESC'] },
});
```

```typescript title="Execute with additional conditions"
// featured = true on top of the list's own query
const items = list.catalog.query.execute({
  queries: [{ operator: 'eq', attribute: 'featured', value: true }],
  count: 10,
});
```

### get()

Returns the current query state. This is the core method that `current()` wraps.

**Signature:**

```typescript
get(): DcuplGlobalQueryOptions
```

**Returns:** `DcuplGlobalQueryOptions` - Current query configuration

**Examples:**

```typescript title="Get current query"
const query = list.catalog.query.get();
console.log(query.queries);
```

```typescript title="Save and restore query state"
const savedQuery = list.catalog.query.get();
// ... make changes ...
list.catalog.query.apply(savedQuery, { mode: 'set' }); // root group: replaces the whole query
```

## Analytical functions

`list.catalog.fn.*` runs the six analysis functions on the list's current query. Options, return
shapes and edge cases live on each function's page; errors are listed in
[Functions API → Errors](/sdk/api/functions#errors).

| Method                              | Purpose                                                                    | Reference                        |
| ----------------------------------- | -------------------------------------------------------------------------- | -------------------------------- |
| `facets(options): DcuplFacet[]`     | Filter options with counts for one attribute, counted disjunctively        | [facets()](/sdk/fn/facets)       |
| `aggregate(options): Aggregation`   | `sum`, `avg`, `min`, `max`, `count`, `distinct` and groups of an attribute | [aggregate()](/sdk/fn/aggregate) |
| `suggest(options): Suggestion[]`    | Autocomplete values for an attribute (prefix or regex match)               | [suggest()](/sdk/fn/suggest)     |
| `groupBy(options): GroupByResponse` | Items grouped by an attribute value, with optional aggregates per group    | [groupBy()](/sdk/fn/group-by)    |
| `pivot(options): PivotResponse`     | A pivot table over rows, columns and aggregated values                     | [pivot()](/sdk/fn/pivot)         |
| `metadata(): ListMetadata`          | Current and initial item count, the applied query, attributes and views    | [metadata()](/sdk/fn/metadata)   |

## Type definitions

The query and function types are exported from `@dcupl/common`
(`import type { DcuplQuery } from '@dcupl/common';`); their definitions and examples are in
[Type definitions](/sdk/api/types):
[DcuplQuery](/sdk/api/types#dcuplquery), [DcuplQueryGroup](/sdk/api/types#dcuplquerygroup),
[DcuplListQueryOptions](/sdk/api/types#dcupllistqueryoptions),
[DcuplFacetOptions](/sdk/api/types#dcuplfacetoptions),
[AggregationOptions](/sdk/api/types#aggregationoptions),
[SuggestionOptions](/sdk/api/types#suggestionoptions) and [PivotOptions](/sdk/api/types#pivotoptions).
Operators and their `options` are in the [Query operators reference](/sdk/api/query-operators).

## Complete examples

Worked examples that combine these calls live in the guides:
[Faceted search](/sdk/advanced/faceted-search) (search with facets),
[Range queries](/sdk/queries/query-range) (price range filter),
[aggregate()](/sdk/fn/aggregate) (statistics) and
[Search & autocomplete](/sdk/advanced/search-autocomplete).

## See also

- [Lists API Reference](/sdk/api/lists)
- [Dcupl Class API Reference](/sdk/api/dcupl)
- [Filtering](/sdk/queries/query-filter)
- [Facets](/sdk/fn/facets)
- [Aggregations](/sdk/fn/aggregate)
