Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/cloud-search-rules/05-add-pin.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 4 additions & 1 deletion capabilities/overview.mdx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
title: Capabilities overview
sidebarTitle: Overview
description: Explore all Meilisearch capabilities, from full-text and semantic search to filtering, analytics, and multi-tenancy.
description: Explore all Meilisearch capabilities, from full-text and semantic search to filtering, curation, analytics, and multi-tenancy.
---

Meilisearch provides a comprehensive set of search and data management capabilities. Each capability is documented with an overview, getting started guide, how-to guides, and advanced topics.
Expand All @@ -25,6 +25,9 @@ Meilisearch provides a comprehensive set of search and data management capabilit
<Card title="Filtering, sorting, and faceting" icon="filter" href="/capabilities/filtering_sorting_faceting/overview">
Narrow, order, and categorize results with filters, sort rules, and faceted navigation.
</Card>
<Card title="Search rules" icon="thumbtack" href="/capabilities/search_rules/overview">
Curate search results by pinning selected documents when query- or time-based conditions match.
</Card>
<Card title="Personalization" icon="user" href="/capabilities/personalization/overview">
Re-rank search results based on user context and behavior for tailored experiences.
</Card>
Expand Down
52 changes: 52 additions & 0 deletions capabilities/search_rules/advanced/pinning_behavior.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
---
title: Search rule behavior
sidebarTitle: Pinning behavior
description: Learn how search rules interact with ranking, filters, precedence, and different search modes.
---

This page explains how search rules interact with ranking, filters, matching, and pagination. Read it before building workflows that depend on pinned results in production.

## Pinning does not change ranking

Pinning does not rewrite your ranking rules and does not assign scores to pinned documents. Meilisearch computes organic results first, then inserts the surviving pinned documents at their requested positions. Organic ranking still decides the order of every non-pinned hit.

Pinning is the only supported action today. Boosting, demoting, and burying are planned for future releases.

## Pinned documents do not need to match the query text

A pinned document can appear even when it is not a lexical match for the query. If the rule matches, the document exists, and it passes filters, Meilisearch inserts it into the result list.

This is useful for help centers, promotions, and landing pages, where the document you want to show is not always the best textual match.

## Filters still apply

Pinned documents do not bypass filters. If the current search filters exclude a pinned document, Meilisearch drops it instead of forcing it into the response. This keeps pinned results consistent with visibility, safety, and authorization rules already enforced by your filters.

## Matching behavior of `contains`

The query condition `contains` performs a case-insensitive literal substring match. It is not fuzzy, semantic, or pattern-aware.

For example, `contains: "call history"` matches `where is call history`, but it does not match `history of calls` because the substring order differs.

Search rules do not support regex, wildcards, or numeric-pattern matching (such as "any 6-digit code"). For more flexible matching, create several rules with different `contains` values.

## Precedence between rules

Use `priority` to control which rule wins when several matching rules compete. Lower numeric values take precedence over higher ones.

If you omit `priority`, treat the rule as having the lowest precedence.

## Result-set behavior

Search rules preserve normal response behavior:

- A document should not appear twice if it is both organic and pinned
- Pagination remains coherent
- Facet distribution stays consistent with the final surviving result set
- Search rules work in regular search, hybrid search, federated search, and network search

## Storage model

Search rules are stored at the instance level, not as per-index settings. A single rule can target documents in any index by setting `indexUid` inside the action selector. This keeps curation configuration centralized, but it also means that rules live outside the usual index-settings lifecycle.

For the full list of matching and action capabilities the current version supports (and the ones it does not), see [the overview](/capabilities/search_rules/overview#current-scope).
142 changes: 142 additions & 0 deletions capabilities/search_rules/getting_started.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
---
title: Getting started with search rules
sidebarTitle: Getting started
description: Enable search rules, create your first rule, and verify how pinned results appear in search.
---

This guide walks you through enabling the experimental flag, creating your first rule, and checking how it affects search results. You can do this from the Meilisearch Cloud dashboard or directly against the API.

## Set up from the Meilisearch Cloud dashboard

Open your project in the [Meilisearch Cloud dashboard](https://cloud.meilisearch.com) and select the **Search rules** tab.

### Activate the feature

Search rules are an add-on. On the Search rules tab, click **Enable Search Rules** to turn on the `dynamicSearchRules` experimental flag for the project.

![Meilisearch Cloud Search rules tab with an "Enable Search Rules" button in the add-on panel](/assets/images/cloud-search-rules/01-activate-addon.png)

### Create your first rule

Once the feature is active, the Search rules tab shows a short explainer and a **New rule** button. Click it to start building a rule.

![Search rules landing page with a "New rule" button in the top-right corner](/assets/images/cloud-search-rules/02-create-first-rule.png)

### Fill in the rule's general information

Give the rule a **Rule ID** (used as the `uid`), an optional **Description**, and a **Priority** if several rules might match the same query. Keep the **Active** toggle on to apply the rule at search time.

![Rule editor showing Rule ID "summer-sales", a description, priority 0, and General / Conditions / Actions sections](/assets/images/cloud-search-rules/03-manage-rule.png)

### Add conditions

In the **Conditions** block, click **Add condition** to open the condition dialog. Pick a type (**Query contains**, **Query is empty**, or **Time window**) and fill in the value. Every condition you add is combined with `AND`, so the rule fires only when all conditions are true at the same time.

![Add condition dialog with a "Query contains" type and a "Contains substring" input](/assets/images/cloud-search-rules/04-add-condition.png)

### Pin documents to fixed positions

In the **Actions** block, click **Add pin**. Choose the source **Index**, pick the **Document** to promote, and set its target **Position** in the result list. Repeat for each document you want to pin. When the rule is ready, click **Create rule**.

![Add pin dialog with an index dropdown, a document selector, and a position input](/assets/images/cloud-search-rules/05-add-pin.png)

### Review and manage your rules

Back on the Search rules tab, every rule you have created is listed with its conditions, actions, priority, and active state. Use the row toggle to pause a rule without deleting it, or the icons on the right to edit or remove it.

![Search rules list with one "summer-sales" rule showing its conditions, pin action, priority, and active toggle](/assets/images/cloud-search-rules/06-rules-list.png)

## Set up from the API

Prefer the API? The same flow maps directly to the `/dynamic-search-rules` routes.

### Enable the experimental flag

Send a `PATCH /experimental-features` to turn on the feature:

```json
{
"dynamicSearchRules": true
}
```

While the flag is disabled, the `/dynamic-search-rules` routes reject requests and saved rules do not apply at search time.

### Create a rule

Create a rule with `PATCH /dynamic-search-rules/invoice-help`:

```json
{
"description": "Promote billing help for invoice searches",
"active": true,
"conditions": [
{ "scope": "query", "contains": "invoice" }
],
"actions": [
{
"selector": { "indexUid": "support", "id": "billing-workspace-overview" },
"action": { "type": "pin", "position": 0 }
}
]
}
```

This rule pins the document `billing-workspace-overview` in the `support` index to the first position whenever a query contains the substring `invoice`.

The route behaves as an upsert:

- It returns `201 Created` when the rule does not exist yet
- It returns `200 OK` when you update an existing rule

### Check the stored rule

Retrieve the rule you just created with `GET /dynamic-search-rules/invoice-help`. The response should include the `uid`, conditions, and actions you sent:

```json
{
"uid": "invoice-help",
"description": "Promote billing help for invoice searches",
"active": true,
"conditions": [
{ "scope": "query", "contains": "invoice" }
],
"actions": [
{
"selector": { "indexUid": "support", "id": "billing-workspace-overview" },
"action": { "type": "pin", "position": 0 }
}
]
}
```

### Run a matching search

Send a normal search request to the index, for example `POST /indexes/support/search`:

```json
{
"q": "invoice settings"
}
```

If `billing-workspace-overview` exists in the `support` index and survives the current filters, Meilisearch inserts it at position `0`. The rest of the response is the normal organic result set, with duplicates removed.

Search rules do not replace organic results. Meilisearch still computes them, then inserts the pinned documents on top.

## Next steps

<CardGroup cols={2}>
<Card title="Pin one result for a query" href="/capabilities/search_rules/how_to/pin_one_result_for_query">
Promote a landing page or help article for a query
</Card>
<Card title="Advanced" href="/capabilities/search_rules/advanced/pinning_behavior">
Learn how search rules interact with ranking and filters
</Card>
<Card title="API reference" href="/reference/api/dynamic-search-rules/update-a-dynamic-search-rule-or-create-a-new-one-if-it-doesnt-exist">
Review endpoints and request fields
</Card>
<Card title="Experimental features" href="/resources/help/experimental_features_overview">
Learn more about experimental feature management
</Card>
</CardGroup>
127 changes: 127 additions & 0 deletions capabilities/search_rules/how_to/curate_empty_query.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
---
title: Curate default results for an empty query
description: Use the isEmpty condition to control which documents appear when users open search without typing anything.
---

Many search experiences start with an empty state: a search bar that users click on before typing anything. By default, Meilisearch returns documents in their stored order, which rarely reflects what you want users to see first. The `isEmpty` query condition fires when the query string is empty or missing, so you can curate a welcome list of featured documents without changing any organic ranking.

<Warning>
Search rules are experimental. Enable the `dynamicSearchRules` flag with `PATCH /experimental-features` before creating rules. See [Getting started](/capabilities/search_rules/getting_started#enable-the-experimental-flag).
</Warning>

## Example scenario

On the `support` help center, the search bar is visible on every page. When users focus it without typing anything, they currently see the five oldest documents, which are not the most helpful. You want to replace that default list with three curated articles that cover the most common starting questions:

- `quickstart-overview` at position `0`
- `popular-integrations` at position `1`
- `contact-support` at position `2`

A single rule with an `isEmpty` condition and three pin actions handles this.

## Set up from the Meilisearch Cloud dashboard

Open your project in the [Meilisearch Cloud dashboard](https://cloud.meilisearch.com) and select the **Search rules** tab.

### 1. Create a new rule

Click **New rule**. Give it a descriptive Rule ID such as `empty-state-help`, add a short description, and keep the **Active** toggle on.

![Rule editor with a Rule ID and description filled in](/assets/images/cloud-search-rules/03-manage-rule.png)

### 2. Add an empty query condition

In the **Conditions** block, click **Add condition**. In the dialog:

- Set **Type** to `Query is empty`

`Query is empty` has no additional fields to fill. The condition simply asserts that the search request has no `q` value, or that `q` is an empty string.

Click **Add condition** to save.
Comment on lines +38 to +40
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Include whitespace-only queries in the condition explanation.

This section says Query is empty matches missing q or "", but Line 98 also says it matches whitespace-only q. Add that here too so behavior is stated consistently in one place.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@capabilities/search_rules/how_to/curate_empty_query.mdx` around lines 38 -
40, The explanation for the "Query is empty" condition currently only mentions
missing `q` or `""`; update the text for the `Query is empty` condition to also
state that it matches whitespace-only `q` values (e.g., `"   "`), so the
behavior is consistent with the description later (Line 98) and users understand
that blank/whitespace-only queries are treated as empty; edit the sentence that
currently reads "The condition simply asserts that the search request has no `q`
value, or that `q` is an empty string." to include whitespace-only `q` values as
well.


![Add condition dialog with the "Query is empty" type selected](/assets/images/cloud-search-rules/04-add-condition.png)

### 3. Pin the featured documents

In the **Actions** block, click **Add pin** three times, once per document:

- `support` / `quickstart-overview` at position `0`
- `support` / `popular-integrations` at position `1`
- `support` / `contact-support` at position `2`

![Add pin dialog configured for the first featured document](/assets/images/cloud-search-rules/05-add-pin.png)

### 4. Save the rule

Click **Create rule**. The new rule appears in the Search rules list with the `isEmpty` condition and three pin actions.

![Search rules list with the curated empty-state rule](/assets/images/cloud-search-rules/06-rules-list.png)

## Set up from the API

Send a `PATCH /dynamic-search-rules/empty-state-help`:

```json
{
"description": "Curate the default help-center browse state",
"active": true,
"conditions": [
{ "scope": "query", "isEmpty": true }
],
"actions": [
{
"selector": { "indexUid": "support", "id": "quickstart-overview" },
"action": { "type": "pin", "position": 0 }
},
{
"selector": { "indexUid": "support", "id": "popular-integrations" },
"action": { "type": "pin", "position": 1 }
},
{
"selector": { "indexUid": "support", "id": "contact-support" },
"action": { "type": "pin", "position": 2 }
}
]
}
```

- `isEmpty: true` means the rule only fires when the search request contains no query text.
- `isEmpty` and `contains` are mutually exclusive within a single condition. A condition either matches empty queries or matches queries containing a substring.
- Pinned documents do not need to match the query text, which is convenient here because there is no query text to match.

## When the rule fires

The rule fires whenever Meilisearch receives:

- A search request with `q` missing from the body
- A search request where `q` is the empty string `""`
- A search request where `q` contains only whitespace (case-insensitive, accent-insensitive behavior is irrelevant here)

The rule does not fire for requests with a non-empty query, even a single character. For those, use a `contains` condition instead. See [Pin one result for a query](/capabilities/search_rules/how_to/pin_one_result_for_query).

## Variations and tips

- **Pagination**: if your empty-state UI uses `limit` and `offset` to paginate, the pinned documents only appear on the first page. Users scrolling past position `2` see organic results as usual.
- **Facets and filters**: if users can filter the empty state (for example, by category), pins that do not match the active filters are dropped. The remaining pins stay at their positions, and organic results fill the gaps.
- **Seasonal overrides**: combine `isEmpty` with a time window condition to swap your default browse list during a campaign. See [Schedule a promotion for a limited time](/capabilities/search_rules/how_to/schedule_promotion).
- **Separate rules for separate indexes**: if you maintain multiple indexes with their own empty states (for example, `support` and `products`), create one rule per index. A single action's `indexUid` only controls one pin.

## Next steps

<CardGroup cols={2}>
<Card title="Pin one result for a query" href="/capabilities/search_rules/how_to/pin_one_result_for_query">
Pin a document for a specific query substring
</Card>
<Card title="Pin several results in a fixed order" href="/capabilities/search_rules/how_to/pin_multiple_results">
Control multiple top positions at once
</Card>
<Card title="Schedule a promotion" href="/capabilities/search_rules/how_to/schedule_promotion">
Limit a rule to a campaign window
</Card>
<Card title="Pinning behavior" href="/capabilities/search_rules/advanced/pinning_behavior">
Learn how pins interact with ranking, filters, and precedence
</Card>
<Card title="API reference" href="/reference/api/dynamic-search-rules/update-a-dynamic-search-rule-or-create-a-new-one-if-it-doesnt-exist">
Full request and response shapes
</Card>
</CardGroup>
Loading
Loading