diff --git a/assets/datasets/crm-chats.json b/assets/datasets/crm-chats.json
new file mode 100644
index 000000000..569a62908
--- /dev/null
+++ b/assets/datasets/crm-chats.json
@@ -0,0 +1,14 @@
+[
+ {
+ "id": 0,
+ "client_name": "Natasha Nguyen",
+ "message": "My email is natasha.nguyen@example.com",
+ "time": 1727349362
+ },
+ {
+ "id": 1,
+ "client_name": "Riccardo Rotondo",
+ "message": "No, I changed my email, it's no longer rotondino@example.com, the one you see on my profile is the right one",
+ "time": 1726344418
+ }
+]
diff --git a/assets/datasets/crm-profiles.json b/assets/datasets/crm-profiles.json
new file mode 100644
index 000000000..204e38ddc
--- /dev/null
+++ b/assets/datasets/crm-profiles.json
@@ -0,0 +1,12 @@
+[
+ {
+ "id": 0,
+ "name": "Natasha Nguyen",
+ "email": "natasha.nguyen@example.com"
+ },
+ {
+ "id": 1,
+ "name": "Riccardo Rotondo",
+ "email": "riccardo.rotondo@example.com"
+ }
+]
diff --git a/assets/datasets/crm-tickets.json b/assets/datasets/crm-tickets.json
new file mode 100644
index 000000000..4a61886cb
--- /dev/null
+++ b/assets/datasets/crm-tickets.json
@@ -0,0 +1,16 @@
+[
+ {
+ "id": 0,
+ "time": 1727349362,
+ "client_name": "Natasha Nguyen",
+ "type": "complaint",
+ "title": "I'm not receiving any emails"
+ },
+ {
+ "id": 1,
+ "time": 1701448312,
+ "client_name": "Riccardo Rotondo",
+ "type": "support",
+ "title": "Please remove my email from your mailing list"
+ }
+]
diff --git a/config/sidebar-learn.json b/config/sidebar-learn.json
index f8b4ed8d6..b2debe918 100644
--- a/config/sidebar-learn.json
+++ b/config/sidebar-learn.json
@@ -253,6 +253,22 @@
}
]
},
+ {
+ "title": "Multi-search",
+ "slug": "multi_search",
+ "routes": [
+ {
+ "source": "learn/multi_search/performing_federated_search.mdx",
+ "label": "Using multi-search to perform a federated search",
+ "slug": "performing_federated_search"
+ },
+ {
+ "source": "learn/multi_search/multi_search_vs_federated_search.mdx",
+ "label": "Differences between multi-search and federated search",
+ "slug": "multi_search_vs_federated_search"
+ }
+ ]
+ },
{
"title": "Update and migration",
"slug": "update_and_migration",
diff --git a/learn/multi_search/multi_search_vs_federated_search.mdx b/learn/multi_search/multi_search_vs_federated_search.mdx
new file mode 100644
index 000000000..d8d275697
--- /dev/null
+++ b/learn/multi_search/multi_search_vs_federated_search.mdx
@@ -0,0 +1,26 @@
+---
+title: Differences between multi-search and federated search — Meilisearch API reference
+description: This article defines multi-search and federated search and then describes the different uses of each.
+---
+
+# Differences between multi-search and federated search
+
+This article defines multi-search and federated search and then describes the different uses of each.
+
+## What is multi-search?
+
+Multi-search, also called multi-index search, is a search operation that makes multiple queries at the same time. These queries may target different indexes. Meilisearch then returns a separate list results for each query. Use the `/multi-search` route to perform multi-searches.
+
+Multi-search favors discovery scenarios, where users might not have a clear idea of what they need and searches might have many valid results.
+
+## What is federated search?
+
+Federated search is a type of multi-index search. This operation also makes multiple search requests at the same time, but returns a single list with the most relevant results from all queries. Use the `/multi-search` route and specify a non-null value for `federation` to perform a federated search.
+
+Federated search favors scenarios where users have a clear idea of what they need and expect a single best top result.
+
+## Use cases
+
+Because multi-search groups results by query, it is often useful when the origin and type of document contain information relevant to your users. For example, a person searching for `shygirl` in a music streaming application is likely to appreciate seeing separate results for matching artists, albums, and individual tracks.
+
+Federated search is a better approach when the source of the information is not relevant to your users. For example, a person searching for a client's email in a CRM application is unlikely to care whether this email comes from chat logs, support tickets, or other data sources.
diff --git a/learn/multi_search/performing_federated_search.mdx b/learn/multi_search/performing_federated_search.mdx
new file mode 100644
index 000000000..239a3f1c0
--- /dev/null
+++ b/learn/multi_search/performing_federated_search.mdx
@@ -0,0 +1,143 @@
+---
+title: Using multi-search to perform a federated search — Meilisearch API reference
+description: In this tutorial you will see how to perform a query searching multiple indexes at the same time to obtain a single list of results.
+---
+
+# Using multi-search to perform a federated search
+
+Meilisearch allows you to make multiple search requests at the same time with the `/multi-search` endpoint. A federated search is a multi-search that returns results from multiple queries in a single list.
+
+In this tutorial you will see how to create separate indexes containing different types of data from a CRM application. You will then perform a query searching all these indexes at the same time to obtain a single list of results.
+
+## Requirements
+
+- A running Meilisearch project
+- A command-line console
+
+## Create three indexes
+
+Download the following datasets: `crm-chats.json`, `crm-profiles.json`, and `crm-tickets.json` containing data from a fictional CRM application.
+
+Add the datasets to Meilisearch and create three separate indexes, `profiles`, `chats`, and `tickets`:
+
+```sh
+curl -X POST 'http://localhost:7700/indexes/profiles' -H 'Content-Type: application/json' --data-binary @crm-profiles.json &&
+curl -X POST 'http://localhost:7700/indexes/chats' -H 'Content-Type: application/json' --data-binary @crm-chats.json &&
+curl -X POST 'http://localhost:7700/indexes/tickets' -H 'Content-Type: application/json' --data-binary @crm-tickets.json
+```
+
+[Use the tasks endpoint](/learn/async/working_with_tasks) to check the indexing status. Once Meilisearch successfully indexed all three datasets, you are ready to perform a federated search.
+
+## Perform a federated search
+
+When you are looking for Natasha Nguyen's email address in your CRM application, you may not know whether you will find it in a chat log, among the existing customer profiles, or in a recent support ticket. In this situation, you can use federated search to search across all possible sources and receive a single list of results.
+
+Use the `/multi-search` endpoint with the `federation` parameter to query the three indexes simultaneously:
+
+```sh
+curl \
+ -X POST 'http://localhost:7700/multi-search' \
+ -H 'Content-Type: application/json' \
+ --data-binary '{
+ "federation": {},
+ "queries": [
+ {
+ "indexUid": "chats",
+ "q": "natasha"
+ },
+ {
+ "indexUid": "profiles",
+ "q": "natasha"
+ },
+ {
+ "indexUid": "tickets",
+ "q": "natasha"
+ }
+ ]
+ }'
+```
+
+Meilisearch should respond with a single list of search results:
+
+```json
+{
+ "hits": [
+ {
+ "id": 0,
+ "client_name": "Natasha Nguyen",
+ "message": "My email is natasha.nguyen@example.com",
+ "time": 1727349362,
+ "_federation": {
+ "indexUid": "chats",
+ "queriesPosition": 0
+ }
+ },
+ …
+ ],
+ "processingTimeMs": 0,
+ "limit": 20,
+ "offset": 0,
+ "estimatedTotalHits": 3,
+ "semanticHitCount": 0
+}
+```
+
+## Promote results from a specific index
+
+Since this is a CRM application, users have profiles with their preferred contact information. If you want to search for Riccardo Rotondo's preferred email, you can boost documents in the `profiles` index.
+
+Use the `weight` property of the `federation` parameter to boost results coming from a specific query:
+
+```sh
+curl \
+ -X POST 'http://localhost:7700/multi-search' \
+ -H 'Content-Type: application/json' \
+ --data-binary '{
+ "federation": {},
+ "queries": [
+ {
+ "indexUid": "chats",
+ "q": "rotondo"
+ },
+ {
+ "indexUid": "profiles",
+ "q": "rotondo",
+ "federationOptions": {
+ "weight": 1.2
+ }
+ },
+ {
+ "indexUid": "tickets",
+ "q": "rotondo"
+ }
+ ]
+ }'
+```
+
+This request will lead to results from the query targeting `profile` ranking higher than documents from other queries:
+
+```json
+{
+ "hits": [
+ {
+ "id": 1,
+ "name": "Riccardo Rotondo",
+ "email": "riccardo.rotondo@example.com",
+ "_federation": {
+ "indexUid": "profiles",
+ "queriesPosition": 1
+ }
+ },
+ …
+ ],
+ "processingTimeMs": 0,
+ "limit": 20,
+ "offset": 0,
+ "estimatedTotalHits": 3,
+ "semanticHitCount": 0
+}
+```
+
+## Conclusion
+
+You have created three indexes, then performed a federated multi-index search to receive all results in a single list. You then used `weight` to boost results from the index most likely to contain the information you wanted.