Skip to content

v1.16: /export route #3315

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Jul 31, 2025
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
12 changes: 12 additions & 0 deletions .code-samples.meilisearch.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1467,6 +1467,18 @@ related_results_similar_1: |-
"id": 192,
"embedder": "EMBEDDER_NAME"
}'
export_post_1: |-
curl \
-X POST 'MEILISEARCH_URL/export' \
-H 'Content-Type: application/json' \
--data-binary '{
"url": "TARGET_INSTANCE_URL",
"indexes": {
"*": {
"overrideSettings": true
}
}
}'

### Code samples for experimental features
experimental_get_metrics_1: |-
Expand Down
3 changes: 2 additions & 1 deletion docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,8 @@
"reference/api/dump",
"reference/api/experimental_features",
"reference/api/metrics",
"reference/api/logs"
"reference/api/logs",
"reference/api/export"
]
},
{
Expand Down
68 changes: 68 additions & 0 deletions reference/api/export.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
---
title: Export
description: "Migrate between instances with the `/export` route"
---

import { RouteHighlighter } from '/snippets/route_highlighter.mdx'

import CodeSamplesExperimentalDeleteLogsStream1 from '/snippets/samples/code_samples_experimental_delete_logs_stream_1.mdx';

Use the `/export` route to transfer data from your origin instance to a remote target instance. This is particularly useful when migrating from your local development environment to a Meilisearch Cloud instance.

## Migrate database between instances

<RouteHighlighter method="POST" path="/export" />

Migrate data from the origin instance to a target instance.

Migration is an additive operation. If the exported indexes already exist in the target instance, Meilisearch keeps the existing documents intact and adds the new data to the index. If the same document is present in both the target and origin, Meilisearch replaces the target documents with the new data.

### Body

| Name | Type | Default value | Description |
| ------------------- | ------ | ------------- | --------------------------------------------------------------------------------------------------------- |
| **`url`** * | String | `null` | The target instance's URL address. Required |
| **`apiKey`** * | String | `null` | An API key with full admin access to the target instance |
| **`payloadSize`** * | String | "50 MiB" | A string specifying the payload size in a human-readable format |
| **`indexes`** * | Object | `null` | A set of patterns matching the indexes you want to export. Defaults to all indexes in the origin instance |

#### `url`

A string pointing to a remote Meilisearch instance, including its port if necessary.

This field is required.

#### `apiKey`

A security key with `index.create`, `settings.update`, and `documents.add` permissions to a secured Meilisearch instance.

#### `payloadSize`

The maximum size of each single data payload in a human-readable format such as `"100MiB"`. Larger payloads are generally more efficient, but require significantly more powerful machines.

#### `indexes`

A set of objects whose keys correspond to patterns matching the indexes you want to export. By default, Meilisearch exports all documents across all indexes.

Meilisearch does not override any index settings by default. If the target instance contains an index with the same name as an index you're exporting, Meilisearch uses the settings in the target instance. If the index does not already exist in the target instance, Meilisearch uses the settings in the origin instance.

Each index object accepts the following fields:

- `filter`: a [filter expression](/learn/filtering_and_sorting/filter_expression_reference) defining the subset of documents to export. Optional, defaults to `null`
- `overrideSettings`: if `true`, configures indexes in the target instance with the origin instance settings. Optional, defaults to `false`

### Example

<CodeSamplesExportPost1 />

#### Response

```json
{
"taskUid": 2,
"indexUid": null,
"status": "enqueued",
"type": "export",
"enqueuedAt": "2025-06-26T12:54:10.785864Z"
}
```
20 changes: 20 additions & 0 deletions reference/errors/error_codes.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,26 @@ The [`offset`](/reference/api/documents#query-parameters) parameter is invalid.

The provided `_geo` field of one or more documents is invalid. Meilisearch expects `_geo` to be an object with two fields, `lat` and `lng`, each containing geographic coordinates expressed as a string or floating point number. Read more about `_geo` and how to troubleshoot it in [our dedicated guide](/learn/filtering_and_sorting/geosearch).

## `invalid_export_url`

The export target instance URL is invalid or could not be reached.

## `invalid_export_api_key`

The supplied security key does not have the required permissions to access the target instance.

## `invalid_export_payload_size`

The provided payload size is invalid. The payload size must be a string indicating the maximum payload size in a human-readable format.

## `invalid_export_indexes_patterns`

The provided index pattern is invalid. The index pattern must be an alphanumeric string, optionally including a wildcard.

## `invalid_export_index_filter`

The provided index export filter is not a valid [filter expression](/learn/filtering_and_sorting/filter_expression_reference).

## `invalid_facet_search_facet_name`

The attribute used for the `facetName` field is either not a string or not defined in the [`filterableAttributes` list](/reference/api/settings#filterable-attributes).
Expand Down
2 changes: 1 addition & 1 deletion snippets/samples/code_samples_add_movies_json_1.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ file, _ := os.ReadFile("movies.json")
var movies interface{}
json.Unmarshal([]byte(file), &movies)

client.Index("movies").AddDocuments(&movies)
client.Index("movies").AddDocuments(&movies, nil)
```

```csharp C#
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ documents := []map[string]interface{}{
"release_date": "2019-03-23",
},
}
client.Index("movies").AddDocuments(documents)
client.Index("movies").AddDocuments(documents, nil)
```

```csharp C#
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ documents := []map[string]interface{}{
"genres": "comedy",
},
}
client.Index("movies").UpdateDocuments(documents)
client.Index("movies").UpdateDocuments(documents, nil)
```

```csharp C#
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ await client.GetTasksAsync(new TasksQuery { Statuses = new List<TaskInfoStatus>
```rust Rust
let mut query = TasksQuery::new(&client);
let tasks = query
.with_statuses(["failed", "canceled"])
.with_statuses(["failed"])
.execute()
.await
.unwrap();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,13 @@
curl \
-X GET 'MEILISEARCH_URL/tasks?statuses=failed,canceled'
```

```rust Rust
let mut query = TasksQuery::new(&client);
let tasks = query
.with_statuses(["failed", "canceled"])
.execute()
.await
.unwrap();
```
</CodeGroup>
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,12 @@ curl \
"primaryKey": "id"
}'
```

```rust Rust
let client = Client::new("http://localhost:7700", Some("DEFAULT_ADMIN_API_KEY"));
let task = client
.create_index("medical_records", Some("id"))
.await
.unwrap();
```
</CodeGroup>
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,12 @@
curl -X GET 'MEILISEARCH_URL/keys' \
-H 'Authorization: Bearer MASTER_KEY'
```

```rust Rust
let client = Client::new("http://localhost:7700", Some("MASTER_KEY"));
client
.get_keys()
.await
.unwrap();
```
</CodeGroup>
11 changes: 11 additions & 0 deletions snippets/samples/code_samples_basic_security_tutorial_search_1.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,15 @@ curl \
-H 'Authorization: Bearer DEFAULT_SEARCH_API_KEY' \
--data-binary '{ "q": "appointments" }'
```

```rust Rust
let client = Client::new("http://localhost:7700", Some("DEFAULT_SEARCH_API_KEY"));
let index = client.index("medical_records");
index
.search()
.with_query("appointments")
.execute::<MedicalRecord>()
.await
.unwrap();
```
</CodeGroup>
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ client.index('games').update_filterable_attributes(['release_timestamp'])
```

```go Go
filterableAttributes := []string{"release_timestamp"}
filterableAttributes := []interface{}{"release_timestamp"}
client.Index("games").UpdateFilterableAttributes(&filterableAttributes)
```

Expand Down
2 changes: 1 addition & 1 deletion snippets/samples/code_samples_date_guide_index_1.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ byteValue, _ := io.ReadAll(jsonFile)
var games []map[string]interface{}
json.Unmarshal(byteValue, &games)

client.Index("games").AddDocuments(games)
client.Index("games").AddDocuments(games, nil)
```

```csharp C#
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ client.index('products').update_filterable_attributes([
```

```go Go
filterableAttributes := []string{
filterableAttributes := []interface{}{
"product_id",
"sku",
"url",
Expand Down
10 changes: 10 additions & 0 deletions snippets/samples/code_samples_facet_search_1.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,16 @@ var query = new SearchFacetsQuery()
await client.Index("books").FacetSearchAsync("genres", query);
```

```rust Rust
let res = client.index("books")
.facet_search("genres")
.with_facet_query("fiction")
.with_filter("rating > 3")
.execute()
.await
.unwrap();
```

```dart Dart
await client.index('books').facetSearch(
FacetSearchQuery(
Expand Down
14 changes: 14 additions & 0 deletions snippets/samples/code_samples_facet_search_2.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,20 @@ var newFaceting = new Faceting
await client.Index("books").UpdateFacetingAsync(newFaceting);
```

```rust Rust
let mut facet_sort_setting = BTreeMap::new();
facet_sort_setting.insert("genres".to_string(), FacetSortValue::Count);
let faceting = FacetingSettings {
max_values_per_facet: 100,
sort_facet_values_by: Some(facet_sort_setting),
};

let res = client.index("books")
.set_faceting(&faceting)
.await
.unwrap();
```

```dart Dart
await client.index('books').updateFaceting(
Faceting(
Expand Down
10 changes: 10 additions & 0 deletions snippets/samples/code_samples_facet_search_3.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ client.index('books').facet_search('genres', 'c')
client.Index("books").FacetSearch(&meilisearch.FacetSearchRequest{
FacetQuery: "c",
FacetName: "genres",
ExhaustiveFacetCount: true
})
```

Expand All @@ -53,6 +54,15 @@ var query = new SearchFacetsQuery()
await client.Index("books").FacetSearchAsync("genres", query);
```

```rust Rust
let res = client.index("books")
.facet_search("genres")
.with_facet_query("c")
.execute()
.await
.unwrap();
```

```dart Dart
await client.index('books').facetSearch(
FacetSearchQuery(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ client.index('movie_ratings').update_filterable_attributes(['genres', 'rating',
```

```go Go
filterableAttributes := []string{
filterableAttributes := []interface{}{
"genres",
"rating",
"language",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ client.index('movies').update_filterable_attributes([
```

```go Go
resp, err := client.Index("movies").UpdateFilterableAttributes(&[]string{
resp, err := client.Index("movies").UpdateFilterableAttributes(&[]interface{}{
"director",
"genres",
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ client.index('restaurants').update_filterable_attributes(['_geo'])
```

```go Go
filterableAttributes := []string{
filterableAttributes := []interface{}{
"_geo",
}
client.Index("restaurants").UpdateFilterableAttributes(&filterableAttributes)
Expand Down
4 changes: 4 additions & 0 deletions snippets/samples/code_samples_get_all_batches_1.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,8 @@ $client->getBatches();
```ruby Ruby
client.batches
```

```go Go
client.GetBatches();
```
</CodeGroup>
4 changes: 4 additions & 0 deletions snippets/samples/code_samples_get_batch_1.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,8 @@ $client->getBatch(BATCH_UID);
```ruby Ruby
client.batch(BATCH_UID)
```

```go Go
client.GetBatch(BATCH_UID);
```
</CodeGroup>
4 changes: 4 additions & 0 deletions snippets/samples/code_samples_get_embedders_1.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,8 @@ curl \
```ruby Ruby
client.index('INDEX_NAME').embedders
```

```rust Rust
let embedders = index.get_embedders().await.unwrap();
```
</CodeGroup>
8 changes: 8 additions & 0 deletions snippets/samples/code_samples_get_facet_search_settings_1.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,12 @@ client.index('INDEX_UID').facet_search_setting
```go Go
client.Index("books").GetFacetSearch()
```

```rust Rust
let facet_search: bool = client
.index(INDEX_UID)
.get_facet_search()
.await
.unwrap();
```
</CodeGroup>
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,12 @@ client.index('INDEX_UID').prefix_search
```go Go
client.Index("books").GetPrefixSearch()
```

```rust Rust
let prefix_search: PrefixSearchSettings = client
.index(INDEX_UID)
.get_prefix_search()
.await
.unwrap();
```
</CodeGroup>
Loading
Loading