Skip to content
Open
Show file tree
Hide file tree
Changes from 3 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() {}
}
81 changes: 81 additions & 0 deletions src/test/java/com/meilisearch/sdk/IndexRenameTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
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.*;

public 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.getPath(), equalTo("/indexes/oldIndex"));

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));
}
}
133 changes: 133 additions & 0 deletions src/test/java/com/meilisearch/sdk/SwapIndexesRenameTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
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"));

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, startsWith("["));
assertThat(requestBody, endsWith("]"));
}
}