# Facet and Sort Configuration

The structure and behavior of facets and sorting options returned by the search endpoint are configured through database models managed via the administration interface. These configurations allow customization without code deployment.

**Facet Configuration:**

The `FacetConfiguration` model controls how filterable attributes are displayed as facets in search results. Each configuration includes:

* **Attribute Key**: The attribute identifier (e.g., "color", "size", "price")
* **Attribute Type**: The type of attribute (EAV, global, or custom)
* **Widget Type**: Determines how the facet is displayed:
  * `multiselect`: Standard multi-select dropdown with checkboxes
  * `category`: Hierarchical category tree with navigation
  * `range`: Numeric range slider (e.g., for price, discount)
  * `attribute_value`: Attribute value widget with custom URLs
  * `visual_swatch`: Visual color swatches with hex codes
  * `nested`: Nested attribute combinations
  * `data_source`: Data source/seller selection
  * `null`: Hidden widget (used for price lists in multi-inventory scenarios)
* **Widget Kwargs**: Additional widget configuration (labels, sorting mode, etc.)
* **Facet Type**: Elasticsearch aggregation type and settings
* **Facet Kwargs**: Additional facet aggregation parameters
* **Settings**: Custom settings for the facet configuration

When a Facet Configuration exists for an attribute, it overrides default widget selection logic. If no configuration exists, the system uses fallback rules:

* `category_ids` → Category Widget
* `basket_offer_ids` → Promotion Widget
* All others → Multi Select Widget

Facet Configurations support translation for multi-language sites. The `name` and `widget_kwargs` fields are translatable.

**Sort Options:**

The `SortOption` model defines available sorting options for search results. Each sort option includes:

* **Label**: Display name for the sort option (translatable)
* **Value**: Identifier used in the `sorter` query parameter
* **Elasticsearch Value**: JSON configuration defining how Elasticsearch should sort results. Can include:
  * Field paths (e.g., `products.price`, `products.discount_amount`)
  * Sort direction (`asc` or `desc`)
  * Nested field configurations for product-level sorting
  * Multiple sort criteria (array of sort definitions)
* **Order**: Display order of the sort option
* **Is Default**: Whether this is the default sort option
* **Is Visible**: Whether the sort option appears in the UI

Sort options automatically adapt to inventory strategy context. When an inventory strategy with a price list is active, price-related sort fields are automatically prefixed with the price list ID (e.g., `products.price_1234` instead of `products.price`). Additionally, a secondary sort by `products.listed_id` is automatically appended to ensure consistent ordering.

Sort options are retrieved based on the current language and filtered to show only visible options, ordered by default status and custom order.

#### Dynamic Filter

Use the `X-SEARCH-DYNAMIC-FILTER` header to include only products matching specific criteria. The header value must be a base64-encoded JSON object containing filter rules.

**Step 1: Create the filter JSON**

Build a JSON object with field paths as keys and filter values as arrays. Field paths use dot notation (e.g., `products.sku.raw` for SKU, `products.category_ids` for categories).

Example: Filter products with specific SKUs

```json
{"products.sku.raw": ["2672881040611", "2672881031947"]}
```

**Step 2: Base64 encode the JSON**

Encode the JSON string using base64 encoding.

Example:

```
Original: {"products.sku.raw": ["2672881040611","2672881031947"]}
Encoded: eyJwcm9kdWN0cy5za3UucmF3IjogWyIyNjcyODgxMDQwNjExIiwiMjY3Mjg4MTAzMTk0NyJdfQ==
```

**Step 3: Add the header to your request**

Include the `X-SEARCH-DYNAMIC-FILTER` header with the base64-encoded value.

Example request:

```bash
curl --location 'https://{commerce_url}/list/?format=json' \
  --header 'X-SEARCH-DYNAMIC-FILTER: eyJwcm9kdWN0cy5za3UucmF3IjogWyIyNjcyODgxMDQwNjExIiwiMjY3Mjg4MTAzMTk0NyJdfQ=='
```

This will return only products with SKUs "2672881040611" or "2672881031947".

#### Dynamic Exclude

Use the `X-SEARCH-DYNAMIC-EXCLUDE` header to exclude products matching specific criteria. The header value must be a base64-encoded JSON object containing exclude rules.

**Step 1: Create the exclude JSON**

Build a JSON object with field paths as keys and exclude values as arrays.

Example: Exclude products from a specific category

```json
{"products.category_ids": [152]}
```

**Step 2: Base64 encode the JSON**

Encode the JSON string using base64 encoding.

Example:

```
Original: {"products.category_ids": [152]}
Encoded: eyJwcm9kdWN0cy5jYXRlZ29yeV9pZHMiOiBbMTUyXX0=
```

**Step 3: Add the header to your request**

Include the `X-SEARCH-DYNAMIC-EXCLUDE` header with the base64-encoded value.

Example request:

```bash
curl --location 'https://{commerce_url}/list/?format=json' \
  --header 'X-SEARCH-DYNAMIC-EXCLUDE: eyJwcm9kdWN0cy5jYXRlZ29yeV9pZHMiOiBbMTUyXX0='
```

This will return all products except those in category 152.

**Notes:**

* Both headers can be used together in the same request
* Filter rules are applied before user-provided query parameters
* Field paths must match Elasticsearch field names (use `.raw` suffix for exact matches on analyzed fields like SKU)
