diff --git a/.code-samples.meilisearch.yaml b/.code-samples.meilisearch.yaml index 2c7cdd86..51c069dd 100644 --- a/.code-samples.meilisearch.yaml +++ b/.code-samples.meilisearch.yaml @@ -664,3 +664,26 @@ post_render_template_1: |- .setInput(input); client.renderTemplate(request); + + +list_dynamic_search_rules_1: |- + DynamicSearchRulesQuery query = new DynamicSearchRulesQuery(); + Results rules = client.listDynamicSearchRules(query); +get_dynamic_search_rule_1: |- + DynamicSearchRule rule = client.getDynamicSearchRule("black-friday"); +patch_dynamic_search_rule_1: |- + List> conditions = List.of( + Map.of("scope", "query", "isEmpty", true), + Map.of("scope", "time", "start", "2025-11-28T00:00:00Z", "end", "2025-11-28T23:59:59Z")); + + List> actions = List.of( + Map.of( + "selector", Map.of("indexUid", "products", "id", "123"), + "action", Map.of("type", "pin", "position", 1))); + + DynamicSearchRule rule = new DynamicSearchRule( + "black-friday", "Black Friday 2025 rules", 10, true, conditions, actions); + + TaskInfo task = client.updateDynamicSearchRule("black-friday", rule); +delete_dynamic_search_rule_1: |- + TaskInfo task = client.deleteDynamicSearchRule("black-friday"); diff --git a/src/main/java/com/meilisearch/sdk/Client.java b/src/main/java/com/meilisearch/sdk/Client.java index 3f4bfed5..d8d4cc68 100644 --- a/src/main/java/com/meilisearch/sdk/Client.java +++ b/src/main/java/com/meilisearch/sdk/Client.java @@ -21,6 +21,7 @@ public class Client { private KeysHandler keysHandler; private JsonHandler jsonHandler; private WebHooksHandler webHooksHandler; + private DynamicSearchRulesHandler dynamicSearchRulesHandler; /** * Calls instance for Meilisearch client @@ -35,6 +36,7 @@ public Client(Config config) { this.keysHandler = new KeysHandler(config); this.jsonHandler = config.jsonHandler; this.webHooksHandler = new WebHooksHandler(config); + this.dynamicSearchRulesHandler = new DynamicSearchRulesHandler(config); } /** @@ -624,4 +626,50 @@ private Boolean isValidUUID(String apiKeyUid) { } return true; } + /** + * Get a list of all dynamic search rules. + * + * @param query Query parameters for pagination and filtering (offset, limit, filter). + * @return Results containing a list of DynamicSearchRule instances. + * @throws MeilisearchException If an error occurs. + */ + public Results listDynamicSearchRules(DynamicSearchRulesQuery query) + throws MeilisearchException { + return this.dynamicSearchRulesHandler.listDynamicSearchRules(query); + } + + /** + * Get a single dynamic search rule by its uid. + * + * @param uid Unique identifier of the dynamic search rule. + * @return A single DynamicSearchRule instance. + * @throws MeilisearchException If an error occurs. + */ + public DynamicSearchRule getDynamicSearchRule(String uid) throws MeilisearchException { + return this.dynamicSearchRulesHandler.getDynamicSearchRule(uid); + } + + /** + * Create a new dynamic search rule, or update it if a rule with the given uid already exists. + * + * @param uid Unique identifier of the dynamic search rule. + * @param dynamicSearchRule Request body containing the rule configuration. + * @return TaskInfo instance for the enqueued upsert operation. + * @throws MeilisearchException If an error occurs. + */ + public TaskInfo updateDynamicSearchRule(String uid, DynamicSearchRule dynamicSearchRule) + throws MeilisearchException { + return this.dynamicSearchRulesHandler.updateDynamicSearchRule(uid, dynamicSearchRule); + } + + /** + * Delete a dynamic search rule. + * + * @param uid Unique identifier of the dynamic search rule. + * @return TaskInfo instance for the enqueued delete operation. + * @throws MeilisearchException If an error occurs. + */ + public TaskInfo deleteDynamicSearchRule(String uid) throws MeilisearchException { + return this.dynamicSearchRulesHandler.deleteDynamicSearchRule(uid); + } } diff --git a/src/main/java/com/meilisearch/sdk/DynamicSearchRulesHandler.java b/src/main/java/com/meilisearch/sdk/DynamicSearchRulesHandler.java new file mode 100644 index 00000000..edead4f9 --- /dev/null +++ b/src/main/java/com/meilisearch/sdk/DynamicSearchRulesHandler.java @@ -0,0 +1,44 @@ +package com.meilisearch.sdk; + +import com.meilisearch.sdk.exceptions.MeilisearchException; +import com.meilisearch.sdk.http.URLBuilder; +import com.meilisearch.sdk.model.DynamicSearchRule; +import com.meilisearch.sdk.model.DynamicSearchRulesQuery; +import com.meilisearch.sdk.model.Results; +import com.meilisearch.sdk.model.TaskInfo; + +class DynamicSearchRulesHandler { + private final HttpClient httpClient; + + protected DynamicSearchRulesHandler(Config config) { + httpClient = config.httpClient; + } + + Results listDynamicSearchRules(DynamicSearchRulesQuery query) + throws MeilisearchException { + return httpClient.post( + dynamicSearchRulesPath().getURL(), query, Results.class, DynamicSearchRule.class); + } + + DynamicSearchRule getDynamicSearchRule(String uid) throws MeilisearchException { + return httpClient.get( + dynamicSearchRulesPath().addSubroute(uid).getURL(), DynamicSearchRule.class); + } + + TaskInfo updateDynamicSearchRule(String uid, DynamicSearchRule dynamicSearchRule) + throws MeilisearchException { + return httpClient.patch( + dynamicSearchRulesPath().addSubroute(uid).getURL(), + dynamicSearchRule, + TaskInfo.class); + } + + TaskInfo deleteDynamicSearchRule(String uid) throws MeilisearchException { + return httpClient.delete( + dynamicSearchRulesPath().addSubroute(uid).getURL(), TaskInfo.class); + } + + private URLBuilder dynamicSearchRulesPath() { + return new URLBuilder("/dynamic-search-rules"); + } +} diff --git a/src/main/java/com/meilisearch/sdk/model/DynamicSearchRule.java b/src/main/java/com/meilisearch/sdk/model/DynamicSearchRule.java new file mode 100644 index 00000000..71f94838 --- /dev/null +++ b/src/main/java/com/meilisearch/sdk/model/DynamicSearchRule.java @@ -0,0 +1,41 @@ +package com.meilisearch.sdk.model; + +import java.io.Serializable; +import java.util.List; +import java.util.Map; +import lombok.Getter; +import lombok.Setter; + +/** + * Meilisearch Dynamic Search Rule. + * + * @see API + * specification + */ +@Getter +@Setter +public class DynamicSearchRule implements Serializable { + protected String uid; + protected String description; + protected int priority; + protected boolean active; + protected List> conditions; + protected List> actions; + + public DynamicSearchRule() {} + + public DynamicSearchRule( + String uid, + String description, + int priority, + boolean active, + List> conditions, + List> actions) { + this.uid = uid; + this.description = description; + this.priority = priority; + this.active = active; + this.conditions = conditions; + this.actions = actions; + } +} diff --git a/src/main/java/com/meilisearch/sdk/model/DynamicSearchRulesQuery.java b/src/main/java/com/meilisearch/sdk/model/DynamicSearchRulesQuery.java new file mode 100644 index 00000000..ecb439cf --- /dev/null +++ b/src/main/java/com/meilisearch/sdk/model/DynamicSearchRulesQuery.java @@ -0,0 +1,27 @@ +package com.meilisearch.sdk.model; + +import java.io.Serializable; +import java.util.Map; + +public class DynamicSearchRulesQuery implements Serializable { + protected Integer offset; + protected Integer limit; + protected Map filter; + + public DynamicSearchRulesQuery() {} + + public DynamicSearchRulesQuery setOffset(int offset) { + this.offset = offset; + return this; + } + + public DynamicSearchRulesQuery setLimit(int limit) { + this.limit = limit; + return this; + } + + public DynamicSearchRulesQuery setFilter(Map filter) { + this.filter = filter; + return this; + } +} diff --git a/src/test/java/com/meilisearch/integration/DynamicSearchRulesTest.java b/src/test/java/com/meilisearch/integration/DynamicSearchRulesTest.java new file mode 100644 index 00000000..6cf67cdc --- /dev/null +++ b/src/test/java/com/meilisearch/integration/DynamicSearchRulesTest.java @@ -0,0 +1,99 @@ +package com.meilisearch.integration; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.hamcrest.MatcherAssert.assertThat; + +import com.meilisearch.integration.classes.AbstractIT; +import com.meilisearch.sdk.exceptions.MeilisearchException; +import com.meilisearch.sdk.model.DynamicSearchRule; +import com.meilisearch.sdk.model.DynamicSearchRulesQuery; +import com.meilisearch.sdk.model.Results; +import com.meilisearch.sdk.model.TaskInfo; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; + +@Tag("integration") +public class DynamicSearchRulesTest extends AbstractIT { + + @BeforeEach + public void initialize() throws MeilisearchException { + this.setUp(); + client.experimentalFeatures(Collections.singletonMap("dynamicSearchRules", true)); + } + + @AfterAll + static void cleanMeilisearch() { + cleanup(); + } + + private DynamicSearchRule buildTestRule(String uid) { + Map queryCondition = Map.of("scope", "query", "isEmpty", true); + Map action = + Map.of( + "selector", Map.of("indexUid", "products"), + "action", Map.of("type", "pin", "position", 1)); + + return new DynamicSearchRule( + uid, "Test rule", 5, true, List.of(queryCondition), List.of(action)); + } + + @Test + public void testUpdateDynamicSearchRule() throws MeilisearchException { + DynamicSearchRule rule = buildTestRule("test-rule"); + + TaskInfo task = client.updateDynamicSearchRule("test-rule", rule); + client.waitForTask(task.getTaskUid()); + + DynamicSearchRule fetched = client.getDynamicSearchRule("test-rule"); + assertThat(fetched.getUid(), equalTo("test-rule")); + assertThat(fetched.getDescription(), equalTo("Test rule")); + assertThat(fetched.getPriority(), equalTo(5)); + assertThat(fetched.isActive(), equalTo(true)); + } + + @Test + public void testGetDynamicSearchRule() throws MeilisearchException { + DynamicSearchRule rule = buildTestRule("test-rule-get"); + TaskInfo task = client.updateDynamicSearchRule("test-rule-get", rule); + client.waitForTask(task.getTaskUid()); + + DynamicSearchRule fetched = client.getDynamicSearchRule("test-rule-get"); + assertThat(fetched, notNullValue()); + assertThat(fetched.getUid(), equalTo("test-rule-get")); + } + + @Test + public void testListDynamicSearchRules() throws MeilisearchException { + TaskInfo task1 = client.updateDynamicSearchRule("rule-one", buildTestRule("rule-one")); + client.waitForTask(task1.getTaskUid()); + TaskInfo task2 = client.updateDynamicSearchRule("rule-two", buildTestRule("rule-two")); + client.waitForTask(task2.getTaskUid()); + + Results results = + client.listDynamicSearchRules(new DynamicSearchRulesQuery()); + + assertThat(results.getResults().length >= 2, equalTo(true)); + } + + @Test + public void testDeleteDynamicSearchRule() throws MeilisearchException { + DynamicSearchRule rule = buildTestRule("test-rule-delete"); + TaskInfo createTask = client.updateDynamicSearchRule("test-rule-delete", rule); + client.waitForTask(createTask.getTaskUid()); + + TaskInfo deleteTask = client.deleteDynamicSearchRule("test-rule-delete"); + client.waitForTask(deleteTask.getTaskUid()); + + MeilisearchException exception = + org.junit.jupiter.api.Assertions.assertThrows( + MeilisearchException.class, + () -> client.getDynamicSearchRule("test-rule-delete")); + assertThat(exception, notNullValue()); + } +}