Skip to content
Open
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
2 changes: 2 additions & 0 deletions .code-samples.meilisearch.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -854,3 +854,5 @@ export_post_1: |-
client.export(request);
compact_index_1: |-
client.index("INDEX_NAME").compact();
rename_an_index_1: |-
client.updateIndex("indexA", null, "indexB");
2 changes: 2 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ dependencies {
testImplementation 'com.squareup.okhttp3:okhttp:4.12.0'
testImplementation 'com.fasterxml.jackson.core:jackson-databind:2.19.0'

testImplementation 'com.squareup.okhttp3:mockwebserver:4.12.0'

// https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind
compileOnly group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.19.0'

Expand Down
1 change: 1 addition & 0 deletions data.ms/VERSION
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
1.26.0
Binary file added data.ms/auth/data.mdb
Binary file not shown.
Binary file added data.ms/auth/lock.mdb
Binary file not shown.
1 change: 1 addition & 0 deletions data.ms/instance-uid
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
e67555e1-d1ac-4ecb-adae-00d5687bbea3
Binary file added data.ms/tasks/data.mdb
Binary file not shown.
Binary file added data.ms/tasks/lock.mdb
Binary file not shown.
15 changes: 10 additions & 5 deletions src/main/java/com/meilisearch/sdk/Client.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,7 @@
import com.meilisearch.sdk.model.*;
import com.meilisearch.sdk.model.batch.req.BatchesQuery;
import com.meilisearch.sdk.model.batch.res.Batch;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.TimeZone;
import java.util.UUID;
import java.util.*;

/** Meilisearch client */
public class Client {
Expand Down Expand Up @@ -169,6 +165,15 @@ public TaskInfo updateIndex(String uid, String primaryKey) throws MeilisearchExc
return this.indexesHandler.updatePrimaryKey(uid, primaryKey);
}

/** Update an index: either update primary key or rename the index by passing indexUid. */
public TaskInfo updateIndex(String uid, String primaryKey, String indexUid)
throws MeilisearchException {
if (indexUid != null) {
return this.indexesHandler.updateIndexUid(uid, indexUid);
}
return this.indexesHandler.updatePrimaryKey(uid, primaryKey);
}

/**
* Deletes single index by its unique identifier
*
Expand Down
14 changes: 14 additions & 0 deletions src/main/java/com/meilisearch/sdk/IndexesHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,20 @@ TaskInfo updatePrimaryKey(String uid, String primaryKey) throws MeilisearchExcep
return httpClient.patch(indexesPath().addSubroute(uid).getURL(), index, TaskInfo.class);
}

/**
* Rename an index by changing its uid.
*
* @param uid Unique identifier of the index to rename
* @param indexUid New unique identifier for the index
* @return Meilisearch API response as TaskInfo
* @throws MeilisearchException if an error occurs
*/
TaskInfo updateIndexUid(String uid, String indexUid) throws MeilisearchException {
HashMap<String, String> body = new HashMap<>();
body.put("indexUid", indexUid);
return httpClient.patch(indexesPath().addSubroute(uid).getURL(), body, TaskInfo.class);
}

/**
* Deletes an index in the Meilisearch instance
*
Expand Down
1 change: 1 addition & 0 deletions src/main/java/com/meilisearch/sdk/model/SearchResult.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ public class SearchResult implements Searchable {
Object facetDistribution;
HashMap<String, FacetRating> facetStats;
int processingTimeMs;
ArrayList<Float> queryVector;
String query;
int offset;
int limit;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ public class SearchResultPaginated implements Searchable {
Object facetDistribution;
HashMap<String, FacetRating> facetStats;
int processingTimeMs;
ArrayList<Float> queryVector;
String query;

public SearchResultPaginated() {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
@Accessors(chain = true)
public class SwapIndexesParams {
protected String[] indexes;
protected Boolean rename;

public SwapIndexesParams() {}
}
83 changes: 83 additions & 0 deletions src/test/java/com/meilisearch/sdk/IndexRenameTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package com.meilisearch.sdk;

import com.meilisearch.sdk.model.TaskInfo;
import okhttp3.mockwebserver.MockResponse;
import okhttp3.mockwebserver.MockWebServer;
import okhttp3.mockwebserver.RecordedRequest;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.io.IOException;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;

class IndexRenameTest {

private MockWebServer mockServer;
private Config config;
private IndexesHandler handler;

@BeforeEach
void setUp() throws IOException {
mockServer = new MockWebServer();
mockServer.start();

String baseUrl = mockServer.url("").toString();
if (baseUrl.endsWith("/")) {
baseUrl = baseUrl.substring(0, baseUrl.length() - 1);
}
config = new Config(baseUrl, "masterKey");
handler = new IndexesHandler(config);
}

@AfterEach
void tearDown() throws IOException {
mockServer.shutdown();
}

@Test
void testRenameIndex() throws Exception {
String responseJson = "{\"taskUid\":123,\"indexUid\":\"indexB\",\"status\":\"enqueued\",\"type\":\"indexUpdate\",\"enqueuedAt\":\"2024-01-01T00:00:00Z\"}";
mockServer.enqueue(new MockResponse()
.setResponseCode(202)
.setBody(responseJson)
.addHeader("Content-Type", "application/json"));

TaskInfo result = handler.updateIndexUid("indexA", "indexB");

assertThat(result, is(notNullValue()));
assertThat(result.getTaskUid(), is(equalTo(123)));

RecordedRequest request = mockServer.takeRequest();
assertThat(request.getMethod(), equalTo("PATCH"));
assertThat(request.getPath(), equalTo("/indexes/indexA"));
assertThat(request.getHeader("Authorization"), equalTo("Bearer masterKey"));

String requestBody = request.getBody().readUtf8();
assertThat(requestBody, containsString("\"indexUid\":\"indexB\""));
}

@Test
void testRenameIndexWithDifferentNames() throws Exception {
String responseJson = "{\"taskUid\":456,\"indexUid\":\"newIndex\",\"status\":\"enqueued\",\"type\":\"indexUpdate\",\"enqueuedAt\":\"2024-01-02T00:00:00Z\"}";
mockServer.enqueue(new MockResponse()
.setResponseCode(202)
.setBody(responseJson)
.addHeader("Content-Type", "application/json"));

TaskInfo result = handler.updateIndexUid("oldIndex", "newIndex");

assertThat(result, is(notNullValue()));
assertThat(result.getTaskUid(), is(equalTo(456)));

RecordedRequest request = mockServer.takeRequest();
assertThat(request.getMethod(), equalTo("PATCH"));
assertThat(request.getPath(), equalTo("/indexes/oldIndex"));
assertThat(request.getHeader("Authorization"), equalTo("Bearer masterKey"));

String requestBody = request.getBody().readUtf8();
assertThat(requestBody, containsString("\"indexUid\":\"newIndex\""));
}
}
32 changes: 32 additions & 0 deletions src/test/java/com/meilisearch/sdk/SearchResultQueryVectorTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.meilisearch.sdk;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;

import com.meilisearch.sdk.json.GsonJsonHandler;
import com.meilisearch.sdk.model.SearchResult;
import org.junit.jupiter.api.Test;

class SearchResultQueryVectorTest {

@Test
void testQueryVectorIsMapped() throws Exception {
String json =
"{"
+ "\"hits\": [],"
+ "\"processingTimeMs\": 1,"
+ "\"query\": \"hello\","
+ "\"queryVector\": [0.1, 0.2, 0.3]"
+ "}";

GsonJsonHandler handler = new GsonJsonHandler();
SearchResult result = handler.decode(json, SearchResult.class);

assertThat(result, is(notNullValue()));
assertThat(result.getQueryVector(), is(notNullValue()));
assertThat(result.getQueryVector().size(), is(3));
assertThat(result.getQueryVector().get(0), equalTo(0.1F));
assertThat(result.getQueryVector().get(1), equalTo(0.2F));
assertThat(result.getQueryVector().get(2), equalTo(0.3F));
}
}
138 changes: 138 additions & 0 deletions src/test/java/com/meilisearch/sdk/SwapIndexesRenameTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
package com.meilisearch.sdk;

import com.meilisearch.sdk.model.SwapIndexesParams;
import com.meilisearch.sdk.model.TaskInfo;
import okhttp3.mockwebserver.MockResponse;
import okhttp3.mockwebserver.MockWebServer;
import okhttp3.mockwebserver.RecordedRequest;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.io.IOException;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;

public class SwapIndexesRenameTest {

private MockWebServer mockServer;
private Config config;
private Client client;

@BeforeEach
void setUp() throws IOException {
mockServer = new MockWebServer();
mockServer.start();

String baseUrl = mockServer.url("").toString();
if (baseUrl.endsWith("/")) {
baseUrl = baseUrl.substring(0, baseUrl.length() - 1);
}
config = new Config(baseUrl, "masterKey");
client = new Client(config);
}

@AfterEach
void tearDown() throws IOException {
mockServer.shutdown();
}

@Test
void testSwapIndexesWithRename() throws Exception {
String responseJson = "{\"taskUid\":789,\"status\":\"enqueued\",\"type\":\"indexSwap\",\"enqueuedAt\":\"2024-01-01T00:00:00Z\"}";
mockServer.enqueue(new MockResponse()
.setResponseCode(202)
.setBody(responseJson)
.addHeader("Content-Type", "application/json"));

SwapIndexesParams[] params = {
new SwapIndexesParams()
.setIndexes(new String[]{"indexA", "indexB"})
.setRename(true)
};

TaskInfo result = client.swapIndexes(params);

assertThat(result, is(notNullValue()));
assertThat(result.getTaskUid(), is(equalTo(789)));

RecordedRequest request = mockServer.takeRequest();
assertThat(request.getMethod(), equalTo("POST"));
assertThat(request.getPath(), equalTo("/swap-indexes"));
assertThat(request.getHeader("Authorization"), equalTo("Bearer masterKey"));

String requestBody = request.getBody().readUtf8();
assertThat(requestBody, containsString("\"rename\":true"));
assertThat(requestBody, containsString("\"indexes\""));
assertThat(requestBody, containsString("\"indexA\""));
assertThat(requestBody, containsString("\"indexB\""));
}

@Test
void testSwapIndexesWithoutRename() throws Exception {
String responseJson = "{\"taskUid\":790,\"status\":\"enqueued\",\"type\":\"indexSwap\",\"enqueuedAt\":\"2024-01-02T00:00:00Z\"}";
mockServer.enqueue(new MockResponse()
.setResponseCode(202)
.setBody(responseJson)
.addHeader("Content-Type", "application/json"));

SwapIndexesParams[] params = {
new SwapIndexesParams()
.setIndexes(new String[]{"indexC", "indexD"})
.setRename(false)
};

TaskInfo result = client.swapIndexes(params);

assertThat(result, is(notNullValue()));
assertThat(result.getTaskUid(), is(equalTo(790)));

RecordedRequest request = mockServer.takeRequest();
assertThat(request.getMethod(), equalTo("POST"));
assertThat(request.getPath(), equalTo("/swap-indexes"));
assertThat(request.getHeader("Authorization"), equalTo("Bearer masterKey"));

String requestBody = request.getBody().readUtf8();
assertThat(requestBody, containsString("\"rename\":false"));
assertThat(requestBody, containsString("\"indexC\""));
assertThat(requestBody, containsString("\"indexD\""));
}

@Test
void testSwapMultipleIndexPairs() throws Exception {
String responseJson = "{\"taskUid\":791,\"status\":\"enqueued\",\"type\":\"indexSwap\",\"enqueuedAt\":\"2024-01-03T00:00:00Z\"}";
mockServer.enqueue(new MockResponse()
.setResponseCode(202)
.setBody(responseJson)
.addHeader("Content-Type", "application/json"));

SwapIndexesParams[] params = {
new SwapIndexesParams()
.setIndexes(new String[]{"indexA", "indexB"})
.setRename(true),
new SwapIndexesParams()
.setIndexes(new String[]{"indexC", "indexD"})
.setRename(false)
};

TaskInfo result = client.swapIndexes(params);

assertThat(result, is(notNullValue()));
assertThat(result.getTaskUid(), is(equalTo(791)));

RecordedRequest request = mockServer.takeRequest();
String requestBody = request.getBody().readUtf8();

assertThat(requestBody, containsString("\"indexA\""));
assertThat(requestBody, containsString("\"indexB\""));
assertThat(requestBody, containsString("\"indexC\""));
assertThat(requestBody, containsString("\"indexD\""));
assertThat(requestBody, containsString("\"rename\":true"));
assertThat(requestBody, containsString("\"rename\":false"));

String trimmedBody = requestBody.trim();
assertThat(trimmedBody, startsWith("["));
assertThat(trimmedBody, endsWith("]"));
}
}
Loading