From 0926b2286057eb9a0e4eae3af33e8a1276fea218 Mon Sep 17 00:00:00 2001 From: ernestorbemx Date: Fri, 8 Aug 2025 01:29:33 -0600 Subject: [PATCH 1/4] Add support for export API --- .code-samples.meilisearch.yaml | 3 + src/main/java/com/meilisearch/sdk/Client.java | 12 +++ .../meilisearch/sdk/ExportIndexFilter.java | 28 +++++ .../com/meilisearch/sdk/ExportRequest.java | 33 ++++++ .../meilisearch/integration/ClientTest.java | 20 ++++ .../meilisearch/sdk/ExportRequestTest.java | 100 ++++++++++++++++++ 6 files changed, 196 insertions(+) create mode 100644 src/main/java/com/meilisearch/sdk/ExportIndexFilter.java create mode 100644 src/main/java/com/meilisearch/sdk/ExportRequest.java create mode 100644 src/test/java/com/meilisearch/sdk/ExportRequestTest.java diff --git a/.code-samples.meilisearch.yaml b/.code-samples.meilisearch.yaml index d46b4f9f7..edcf2d1ad 100644 --- a/.code-samples.meilisearch.yaml +++ b/.code-samples.meilisearch.yaml @@ -843,3 +843,6 @@ update_localized_attribute_settings_1: |- ); reset_localized_attribute_settings_1: |- client.index("INDEX_NAME").resetLocalizedAttributesSettings(); +export_post_1: |- + ExportRequest request = ExportRequest.builder().setUrl("http://anothermeiliinstance:7070").build(); + client.export(request); diff --git a/src/main/java/com/meilisearch/sdk/Client.java b/src/main/java/com/meilisearch/sdk/Client.java index ba0810134..b9a60003b 100644 --- a/src/main/java/com/meilisearch/sdk/Client.java +++ b/src/main/java/com/meilisearch/sdk/Client.java @@ -218,6 +218,18 @@ public TaskInfo createSnapshot() throws MeilisearchException { return config.httpClient.post("/snapshots", "", TaskInfo.class); } + /** + * Triggers the export of documents between Meilisearch Instances. + * + * @param request Export request parameters + * @return Meilisearch API response as TaskInfo + * @throws MeilisearchException if an error occurs + * @see API specification + */ + public TaskInfo export(ExportRequest request) throws MeilisearchException { + return config.httpClient.post("/export", request, TaskInfo.class); + } + /** * Gets the status and availability of a Meilisearch instance * diff --git a/src/main/java/com/meilisearch/sdk/ExportIndexFilter.java b/src/main/java/com/meilisearch/sdk/ExportIndexFilter.java new file mode 100644 index 000000000..a5b5f4e2f --- /dev/null +++ b/src/main/java/com/meilisearch/sdk/ExportIndexFilter.java @@ -0,0 +1,28 @@ +package com.meilisearch.sdk; + +import lombok.*; +import org.json.JSONObject; + +@Builder +@AllArgsConstructor(access = AccessLevel.PACKAGE) +@NoArgsConstructor(access = AccessLevel.PACKAGE) +@Getter +@Setter +public class ExportIndexFilter { + private String filter; + @Builder.Default private boolean overrideSettings = false; + + /** + * Method that returns the JSON String of the ExportRequest + * + * @return JSON String of the ExportRequest query + */ + @Override + public String toString() { + JSONObject jsonObject = + new JSONObject() + .putOpt("filter", this.filter) + .putOpt("overrideSettings", this.overrideSettings); + return jsonObject.toString(); + } +} diff --git a/src/main/java/com/meilisearch/sdk/ExportRequest.java b/src/main/java/com/meilisearch/sdk/ExportRequest.java new file mode 100644 index 000000000..dfd56d282 --- /dev/null +++ b/src/main/java/com/meilisearch/sdk/ExportRequest.java @@ -0,0 +1,33 @@ +package com.meilisearch.sdk; + +import java.util.Map; +import lombok.*; +import org.json.JSONObject; + +@Builder +@AllArgsConstructor(access = AccessLevel.PACKAGE) +@NoArgsConstructor(access = AccessLevel.PACKAGE) +@Getter +@Setter +public class ExportRequest { + private String url; + private String apiKey; + private String payloadSize; + private Map indexes; + + /** + * Method that returns the JSON String of the ExportRequest + * + * @return JSON String of the ExportRequest query + */ + @Override + public String toString() { + JSONObject jsonObject = + new JSONObject() + .put("url", this.url) + .putOpt("apiKey", this.apiKey) + .putOpt("payloadSize", this.payloadSize) + .putOpt("indexes", this.indexes); + return jsonObject.toString(); + } +} diff --git a/src/test/java/com/meilisearch/integration/ClientTest.java b/src/test/java/com/meilisearch/integration/ClientTest.java index 82cb4656a..2b4777675 100644 --- a/src/test/java/com/meilisearch/integration/ClientTest.java +++ b/src/test/java/com/meilisearch/integration/ClientTest.java @@ -7,12 +7,16 @@ import com.google.gson.*; import com.meilisearch.integration.classes.AbstractIT; import com.meilisearch.integration.classes.TestData; +import com.meilisearch.sdk.ExportIndexFilter; +import com.meilisearch.sdk.ExportRequest; import com.meilisearch.sdk.Index; import com.meilisearch.sdk.exceptions.MeilisearchApiException; import com.meilisearch.sdk.exceptions.MeilisearchException; import com.meilisearch.sdk.model.*; import com.meilisearch.sdk.utils.Movie; import java.lang.reflect.Modifier; +import java.util.HashMap; +import java.util.Map; import org.junit.jupiter.api.*; @Tag("integration") @@ -308,6 +312,22 @@ public void testCreateSnapshot() throws Exception { assertThat(snapshot.getType(), is(equalTo("snapshotCreation"))); } + /** Test call to initiate export */ + @Test + public void testExport() throws Exception { + Map indexes = new HashMap<>(); + indexes.put("*", ExportIndexFilter.builder().filter("genres = action").build()); + + ExportRequest payload = + ExportRequest.builder().url(getMeilisearchHost()).indexes(indexes).build(); + TaskInfo task = client.export(payload); + client.waitForTask(task.getTaskUid()); + Task snapshot = client.getTask(task.getTaskUid()); + + assertThat(task.getStatus(), is(equalTo(TaskStatus.ENQUEUED))); + assertThat(snapshot.getType(), is(equalTo("export"))); + } + /** * Test the exclusion of transient fields. * diff --git a/src/test/java/com/meilisearch/sdk/ExportRequestTest.java b/src/test/java/com/meilisearch/sdk/ExportRequestTest.java new file mode 100644 index 000000000..8bac1ab93 --- /dev/null +++ b/src/test/java/com/meilisearch/sdk/ExportRequestTest.java @@ -0,0 +1,100 @@ +package com.meilisearch.sdk; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.nullValue; + +import java.util.HashMap; +import java.util.Map; +import org.json.JSONObject; +import org.junit.jupiter.api.Test; + +public class ExportRequestTest { + + @Test + void toStringSimpleExportIndexFilter() { + ExportIndexFilter filter = ExportIndexFilter.builder().build(); + String expected = "{\"overrideSettings\":false}"; + assertThat(filter.toString(), is(equalTo(expected))); + assertThat(filter.getFilter(), is(nullValue())); + assertThat(filter.isOverrideSettings(), is(false)); + } + + @Test + void toStringExportIndexFilterWithOverride() { + ExportIndexFilter filter = ExportIndexFilter.builder().overrideSettings(true).build(); + String expected = "{\"overrideSettings\":true}"; + assertThat(filter.toString(), is(equalTo(expected))); + assertThat(filter.isOverrideSettings(), is(true)); + } + + @Test + void toStringExportIndexFilterWithFilter() { + ExportIndexFilter filter = ExportIndexFilter.builder().filter("status = 'active'").build(); + String expected = "{\"filter\":\"status = 'active'\",\"overrideSettings\":false}"; + assertThat(filter.toString(), is(equalTo(expected))); + assertThat(filter.getFilter(), is(equalTo("status = 'active'"))); + } + + @Test + void toStringSimpleExportRequest() { + ExportRequest request = + ExportRequest.builder().url("http://localhost:7711").payloadSize("123 MiB").build(); + JSONObject json = new JSONObject(request.toString()); + assertThat(json.getString("url"), is(equalTo("http://localhost:7711"))); + assertThat(json.getString("payloadSize"), is(equalTo("123 MiB"))); + assertThat(json.isNull("apiKey"), is(true)); + assertThat(json.isNull("indexes"), is(true)); + } + + @Test + void toStringExportRequestWithIndexes() { + Map indexes = new HashMap<>(); + indexes.put("*", ExportIndexFilter.builder().overrideSettings(true).build()); + + ExportRequest request = + ExportRequest.builder() + .url("http://localhost:7711") + .payloadSize("123 MiB") + .indexes(indexes) + .build(); + + String expected = + "{\"url\":\"http://localhost:7711\",\"payloadSize\":\"123 MiB\",\"indexes\":{\"*\":{\"overrideSettings\":true}}}"; + JSONObject expectedJson = new JSONObject(expected); + JSONObject json = new JSONObject(request.toString()); + + assertThat(expectedJson.toString(), is(json.toString())); + + assertThat(json.getString("url"), is(equalTo("http://localhost:7711"))); + assertThat(json.getString("payloadSize"), is(equalTo("123 MiB"))); + assertThat(json.isNull("apiKey"), is(true)); + JSONObject indexesJson = json.getJSONObject("indexes"); + JSONObject starIndex = indexesJson.getJSONObject("*"); + assertThat(starIndex.isNull("filter"), is(true)); + assertThat(starIndex.getBoolean("overrideSettings"), is(true)); + } + + @Test + void gettersExportRequest() { + Map indexes = new HashMap<>(); + indexes.put( + "myindex", + ExportIndexFilter.builder().filter("id > 10").overrideSettings(false).build()); + + ExportRequest request = + ExportRequest.builder() + .url("http://localhost:7711") + .apiKey("mykey") + .payloadSize("50 MiB") + .indexes(indexes) + .build(); + + assertThat(request.getUrl(), is(equalTo("http://localhost:7711"))); + assertThat(request.getApiKey(), is(equalTo("mykey"))); + assertThat(request.getPayloadSize(), is(equalTo("50 MiB"))); + assertThat(request.getIndexes().get("myindex").getFilter(), is(equalTo("id > 10"))); + assertThat(request.getIndexes().get("myindex").isOverrideSettings(), is(false)); + } +} From 6778982a43b42a4e5c1fcbb95278f0a023110088 Mon Sep 17 00:00:00 2001 From: ernestorbemx Date: Sat, 9 Aug 2025 21:42:47 -0600 Subject: [PATCH 2/4] Follow CodeRabbit review suggestions --- .code-samples.meilisearch.yaml | 2 +- src/main/java/com/meilisearch/sdk/Client.java | 2 +- .../com/meilisearch/sdk/ExportIndexFilter.java | 16 ++++++++++------ .../com/meilisearch/integration/ClientTest.java | 4 ++-- 4 files changed, 14 insertions(+), 10 deletions(-) diff --git a/.code-samples.meilisearch.yaml b/.code-samples.meilisearch.yaml index edcf2d1ad..bec0b3e1d 100644 --- a/.code-samples.meilisearch.yaml +++ b/.code-samples.meilisearch.yaml @@ -844,5 +844,5 @@ update_localized_attribute_settings_1: |- reset_localized_attribute_settings_1: |- client.index("INDEX_NAME").resetLocalizedAttributesSettings(); export_post_1: |- - ExportRequest request = ExportRequest.builder().setUrl("http://anothermeiliinstance:7070").build(); + ExportRequest request = ExportRequest.builder().url("http://anothermeiliinstance:7070").build(); client.export(request); diff --git a/src/main/java/com/meilisearch/sdk/Client.java b/src/main/java/com/meilisearch/sdk/Client.java index b9a60003b..3a871eb88 100644 --- a/src/main/java/com/meilisearch/sdk/Client.java +++ b/src/main/java/com/meilisearch/sdk/Client.java @@ -219,7 +219,7 @@ public TaskInfo createSnapshot() throws MeilisearchException { } /** - * Triggers the export of documents between Meilisearch Instances. + * Triggers the export of documents between Meilisearch instances. * * @param request Export request parameters * @return Meilisearch API response as TaskInfo diff --git a/src/main/java/com/meilisearch/sdk/ExportIndexFilter.java b/src/main/java/com/meilisearch/sdk/ExportIndexFilter.java index a5b5f4e2f..cf0caafac 100644 --- a/src/main/java/com/meilisearch/sdk/ExportIndexFilter.java +++ b/src/main/java/com/meilisearch/sdk/ExportIndexFilter.java @@ -13,16 +13,20 @@ public class ExportIndexFilter { @Builder.Default private boolean overrideSettings = false; /** - * Method that returns the JSON String of the ExportRequest + * Method that returns the JSON String of the ExportIndexFilter * - * @return JSON String of the ExportRequest query + * @return JSON String of the ExportIndexFilter query */ @Override public String toString() { - JSONObject jsonObject = - new JSONObject() - .putOpt("filter", this.filter) - .putOpt("overrideSettings", this.overrideSettings); + JSONObject jsonObject = new JSONObject(); + if (this.filter != null) { + jsonObject.put("filter", this.filter); + } + if (this.overrideSettings) { + jsonObject.put("overrideSettings", true); + } + return jsonObject.toString(); } } diff --git a/src/test/java/com/meilisearch/integration/ClientTest.java b/src/test/java/com/meilisearch/integration/ClientTest.java index 2b4777675..e288ce3b1 100644 --- a/src/test/java/com/meilisearch/integration/ClientTest.java +++ b/src/test/java/com/meilisearch/integration/ClientTest.java @@ -322,10 +322,10 @@ public void testExport() throws Exception { ExportRequest.builder().url(getMeilisearchHost()).indexes(indexes).build(); TaskInfo task = client.export(payload); client.waitForTask(task.getTaskUid()); - Task snapshot = client.getTask(task.getTaskUid()); + Task exportTask = client.getTask(task.getTaskUid()); assertThat(task.getStatus(), is(equalTo(TaskStatus.ENQUEUED))); - assertThat(snapshot.getType(), is(equalTo("export"))); + assertThat(exportTask.getType(), is(equalTo("export"))); } /** From 071fb72f840a015033d66faa75f9f862a11c3f93 Mon Sep 17 00:00:00 2001 From: ernestorbemx Date: Tue, 26 Aug 2025 23:13:32 -0600 Subject: [PATCH 3/4] Fix ExportRequestTest tests --- .../meilisearch/sdk/ExportRequestTest.java | 33 ++++++++----------- 1 file changed, 13 insertions(+), 20 deletions(-) diff --git a/src/test/java/com/meilisearch/sdk/ExportRequestTest.java b/src/test/java/com/meilisearch/sdk/ExportRequestTest.java index 8bac1ab93..266b446af 100644 --- a/src/test/java/com/meilisearch/sdk/ExportRequestTest.java +++ b/src/test/java/com/meilisearch/sdk/ExportRequestTest.java @@ -3,7 +3,6 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.nullValue; import java.util.HashMap; import java.util.Map; @@ -15,26 +14,25 @@ public class ExportRequestTest { @Test void toStringSimpleExportIndexFilter() { ExportIndexFilter filter = ExportIndexFilter.builder().build(); - String expected = "{\"overrideSettings\":false}"; - assertThat(filter.toString(), is(equalTo(expected))); - assertThat(filter.getFilter(), is(nullValue())); - assertThat(filter.isOverrideSettings(), is(false)); + JSONObject json = new JSONObject(filter.toString()); + assertThat(json.has("overrideSettings"), is(false)); + assertThat(json.has("filter"), is(false)); } @Test void toStringExportIndexFilterWithOverride() { ExportIndexFilter filter = ExportIndexFilter.builder().overrideSettings(true).build(); - String expected = "{\"overrideSettings\":true}"; - assertThat(filter.toString(), is(equalTo(expected))); - assertThat(filter.isOverrideSettings(), is(true)); + JSONObject json = new JSONObject(filter.toString()); + assertThat(json.getBoolean("overrideSettings"), is(true)); + assertThat(json.has("filter"), is(false)); } @Test void toStringExportIndexFilterWithFilter() { ExportIndexFilter filter = ExportIndexFilter.builder().filter("status = 'active'").build(); - String expected = "{\"filter\":\"status = 'active'\",\"overrideSettings\":false}"; - assertThat(filter.toString(), is(equalTo(expected))); - assertThat(filter.getFilter(), is(equalTo("status = 'active'"))); + JSONObject json = new JSONObject(filter.toString()); + assertThat(json.getString("filter"), is(equalTo("status = 'active'"))); + assertThat(json.has("overrideSettings"), is(false)); } @Test @@ -44,8 +42,8 @@ void toStringSimpleExportRequest() { JSONObject json = new JSONObject(request.toString()); assertThat(json.getString("url"), is(equalTo("http://localhost:7711"))); assertThat(json.getString("payloadSize"), is(equalTo("123 MiB"))); - assertThat(json.isNull("apiKey"), is(true)); - assertThat(json.isNull("indexes"), is(true)); + assertThat(json.has("apiKey"), is(false)); + assertThat(json.has("indexes"), is(false)); } @Test @@ -60,19 +58,14 @@ void toStringExportRequestWithIndexes() { .indexes(indexes) .build(); - String expected = - "{\"url\":\"http://localhost:7711\",\"payloadSize\":\"123 MiB\",\"indexes\":{\"*\":{\"overrideSettings\":true}}}"; - JSONObject expectedJson = new JSONObject(expected); JSONObject json = new JSONObject(request.toString()); - assertThat(expectedJson.toString(), is(json.toString())); - assertThat(json.getString("url"), is(equalTo("http://localhost:7711"))); assertThat(json.getString("payloadSize"), is(equalTo("123 MiB"))); - assertThat(json.isNull("apiKey"), is(true)); + assertThat(json.has("apiKey"), is(false)); JSONObject indexesJson = json.getJSONObject("indexes"); JSONObject starIndex = indexesJson.getJSONObject("*"); - assertThat(starIndex.isNull("filter"), is(true)); + assertThat(starIndex.has("filter"), is(false)); assertThat(starIndex.getBoolean("overrideSettings"), is(true)); } From b1e21b1192d7ee4266cb97821c67d9e3f9ebd4d2 Mon Sep 17 00:00:00 2001 From: ernestorbemx Date: Sun, 21 Sep 2025 18:15:12 -0600 Subject: [PATCH 4/4] Update export API example --- .code-samples.meilisearch.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.code-samples.meilisearch.yaml b/.code-samples.meilisearch.yaml index bec0b3e1d..9d7a310dc 100644 --- a/.code-samples.meilisearch.yaml +++ b/.code-samples.meilisearch.yaml @@ -844,5 +844,7 @@ update_localized_attribute_settings_1: |- reset_localized_attribute_settings_1: |- client.index("INDEX_NAME").resetLocalizedAttributesSettings(); export_post_1: |- - ExportRequest request = ExportRequest.builder().url("http://anothermeiliinstance:7070").build(); + Map indexes = new HashMap<>(); + indexes.put("*", ExportIndexFilter.builder().overrideSettings(true).build()); + ExportRequest request = ExportRequest.builder().url("TARGET_INSTANCE_URL").indexes(indexes).build(); client.export(request);