Skip to content

Commit bb20799

Browse files
authored
Merge pull request #906 from yamiSukehiro2907/feat/support-meilisearch-1.18
Add features of meilisearch 1.18 (queryVector and index renaming)
2 parents c58ce38 + d0df797 commit bb20799

10 files changed

Lines changed: 216 additions & 32 deletions

File tree

.code-samples.meilisearch.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -854,3 +854,5 @@ export_post_1: |-
854854
client.export(request);
855855
compact_index_1: |-
856856
client.index("INDEX_NAME").compact();
857+
rename_an_index_1: |-
858+
client.updateIndex("indexA", null, "indexB");

build.gradle

Lines changed: 19 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
*/
88

99
plugins {
10-
// Apply the java-library plugin to add support for Java Library
1110
id 'java-library'
1211
id 'maven-publish'
1312
id 'signing'
@@ -24,8 +23,8 @@ base {
2423
}
2524

2625
jacoco {
27-
toolVersion = "0.8.8"
28-
reportsDirectory = layout.buildDirectory.dir("$projectDir/tmp/coverage")
26+
toolVersion = "0.8.8"
27+
reportsDirectory = layout.buildDirectory.dir("$projectDir/tmp/coverage")
2928
}
3029

3130
jacocoTestCoverageVerification {
@@ -47,23 +46,24 @@ configurations {
4746
}
4847

4948
dependencies {
50-
// This dependency is used internally, and not exposed to consumers on their own compile classpath.
49+
// Library dependencies
5150
implementation 'com.google.code.gson:gson:2.13.2'
5251
implementation 'org.json:json:20250517'
53-
// https://mvnrepository.com/artifact/org.apache.httpcomponents.client5/httpclient5
5452
api 'com.squareup.okhttp3:okhttp:5.3.0'
5553

56-
// Use JUnit test framework
54+
// JUnit 6
5755
testImplementation(platform('org.junit:junit-bom:6.0.1'))
5856
testImplementation('org.junit.jupiter:junit-jupiter:6.0.1')
59-
// https://mvnrepository.com/artifact/org.mockito/mockito-core
57+
58+
// Test libs
6059
testImplementation 'org.mockito:mockito-core:4.11.0'
6160
testImplementation 'org.hamcrest:hamcrest:3.0'
6261
testImplementation 'com.squareup.okio:okio:3.16.2'
6362
testImplementation 'com.squareup.okhttp3:okhttp:5.3.0'
63+
testImplementation 'com.squareup.okhttp3:mockwebserver:5.3.0'
64+
6465
testImplementation 'com.fasterxml.jackson.core:jackson-databind:2.20.1'
6566

66-
// https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind
6767
compileOnly group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.20.1'
6868

6969
// Lombok
@@ -72,16 +72,15 @@ dependencies {
7272
testCompileOnly 'org.projectlombok:lombok:1.18.42'
7373
testAnnotationProcessor 'org.projectlombok:lombok:1.18.42'
7474

75-
// Jwt
75+
// JWT
7676
implementation 'com.auth0:java-jwt:4.5.0'
7777
}
7878

79-
task buildJar(type: Jar) {
79+
tasks.register('buildJar', Jar) {
8080
archiveBaseName = 'meilisearch-java'
8181
from {
8282
configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
83-
}
84-
{
83+
} {
8584
exclude 'META-INF/*.SF'
8685
exclude 'META-INF/*.DSA'
8786
exclude 'META-INF/*.RSA'
@@ -91,11 +90,11 @@ task buildJar(type: Jar) {
9190

9291
test {
9392
useJUnitPlatform {
94-
excludeTags 'integration'
93+
excludeTags 'integration'
9594
}
9695
finalizedBy jacocoTestReport
9796
testLogging {
98-
events 'passed', 'skipped', 'failed'
97+
events 'passed', 'skipped', 'failed'
9998
}
10099
}
101100

@@ -109,7 +108,7 @@ jacocoTestReport {
109108
finalizedBy jacocoTestCoverageVerification
110109
}
111110

112-
task integrationTest(type: Test) {
111+
tasks.register('integrationTest', Test) {
113112
useJUnitPlatform {
114113
includeTags 'integration'
115114
}
@@ -128,7 +127,8 @@ java {
128127
}
129128

130129
tasks.withType(JavaCompile).configureEach {
131-
options.compilerArgs += ['-Xlint:deprecation', '-Xlint:unchecked']
130+
options.compilerArgs += ['-Xlint:deprecation', '-Xlint:unchecked']
131+
options.encoding = 'UTF-8'
132132
}
133133

134134
publishing {
@@ -168,13 +168,10 @@ publishing {
168168
nexusPublishing {
169169
repositories {
170170
sonatype {
171-
// Point to new Central Portal staging API (replaces oss.sonatype.org)
172171
nexusUrl.set(uri("https://ossrh-staging-api.central.sonatype.com/service/local/"))
173172
snapshotRepositoryUrl.set(uri("https://central.sonatype.com/repository/maven-snapshots/"))
174-
// Credentials: use Central Portal token (username/password)
175-
username.set(System.getenv("MAVEN_CENTRAL_USERNAME")) // portal token user
176-
password.set(System.getenv("MAVEN_CENTRAL_PASSWORD")) // portal token password
177-
// packageGroup or stagingProfileId not needed if using nexus-publish-plugin
173+
username.set(System.getenv("MAVEN_CENTRAL_USERNAME"))
174+
password.set(System.getenv("MAVEN_CENTRAL_PASSWORD"))
178175
}
179176
}
180177
}
@@ -185,17 +182,13 @@ signing {
185182
}
186183

187184
javadoc {
188-
if(JavaVersion.current().isJava9Compatible()) {
185+
if (JavaVersion.current().isJava9Compatible()) {
189186
options.addBooleanOption('html5', true)
190187
}
191188
}
192189

193190
spotless {
194-
195191
java {
196-
// don't need to set target, it is inferred from java
197-
198-
// apply a specific flavor of google-java-format
199192
googleJavaFormat('1.10.0').aosp()
200193
}
201194
}

src/main/java/com/meilisearch/sdk/Client.java

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,7 @@
1010
import com.meilisearch.sdk.model.*;
1111
import com.meilisearch.sdk.model.batch.req.BatchesQuery;
1212
import com.meilisearch.sdk.model.batch.res.Batch;
13-
import java.util.Date;
14-
import java.util.HashMap;
15-
import java.util.Map;
16-
import java.util.TimeZone;
17-
import java.util.UUID;
13+
import java.util.*;
1814

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

168+
/** Update an index: either update primary key or rename the index by passing indexUid. */
169+
public TaskInfo updateIndex(String uid, String primaryKey, String indexUid)
170+
throws MeilisearchException {
171+
if (indexUid != null) {
172+
return this.indexesHandler.updateIndexUid(uid, indexUid);
173+
}
174+
return this.indexesHandler.updatePrimaryKey(uid, primaryKey);
175+
}
176+
172177
/**
173178
* Deletes single index by its unique identifier
174179
*

src/main/java/com/meilisearch/sdk/IndexesHandler.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
*
1313
* @see <a href="https://www.meilisearch.com/docs/reference/api/indexes">API specification</a>
1414
*/
15-
class IndexesHandler {
15+
public class IndexesHandler {
1616
private final HttpClient httpClient;
1717

1818
/**
@@ -121,6 +121,20 @@ TaskInfo updatePrimaryKey(String uid, String primaryKey) throws MeilisearchExcep
121121
return httpClient.patch(indexesPath().addSubroute(uid).getURL(), index, TaskInfo.class);
122122
}
123123

124+
/**
125+
* Rename an index by changing its uid.
126+
*
127+
* @param uid Unique identifier of the index to rename
128+
* @param indexUid New unique identifier for the index
129+
* @return Meilisearch API response as TaskInfo
130+
* @throws MeilisearchException if an error occurs
131+
*/
132+
TaskInfo updateIndexUid(String uid, String indexUid) throws MeilisearchException {
133+
HashMap<String, String> body = new HashMap<>();
134+
body.put("uid", indexUid);
135+
return httpClient.patch(indexesPath().addSubroute(uid).getURL(), body, TaskInfo.class);
136+
}
137+
124138
/**
125139
* Deletes an index in the Meilisearch instance
126140
*

src/main/java/com/meilisearch/sdk/model/SearchResult.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ public class SearchResult implements Searchable {
1818
Object facetDistribution;
1919
HashMap<String, FacetRating> facetStats;
2020
int processingTimeMs;
21+
ArrayList<Float> queryVector;
2122
String query;
2223
int offset;
2324
int limit;

src/main/java/com/meilisearch/sdk/model/SearchResultPaginated.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ public class SearchResultPaginated implements Searchable {
2323
Object facetDistribution;
2424
HashMap<String, FacetRating> facetStats;
2525
int processingTimeMs;
26+
ArrayList<Float> queryVector;
2627
String query;
2728

2829
public SearchResultPaginated() {}

src/main/java/com/meilisearch/sdk/model/SwapIndexesParams.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
@Accessors(chain = true)
1111
public class SwapIndexesParams {
1212
protected String[] indexes;
13+
protected Boolean rename;
1314

1415
public SwapIndexesParams() {}
1516
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package com.meilisearch.sdk;
2+
3+
import static org.hamcrest.MatcherAssert.assertThat;
4+
import static org.hamcrest.Matchers.*;
5+
6+
import com.meilisearch.sdk.model.TaskInfo;
7+
import okhttp3.mockwebserver.MockResponse;
8+
import okhttp3.mockwebserver.MockWebServer;
9+
import okhttp3.mockwebserver.RecordedRequest;
10+
import org.junit.jupiter.api.AfterEach;
11+
import org.junit.jupiter.api.BeforeEach;
12+
import org.junit.jupiter.api.Test;
13+
14+
class IndexRenameTest {
15+
16+
private MockWebServer server;
17+
private Client client;
18+
19+
@BeforeEach
20+
void setup() throws Exception {
21+
server = new MockWebServer();
22+
server.start();
23+
24+
client = new Client(new Config(server.url("/").toString(), "masterKey"));
25+
}
26+
27+
@AfterEach
28+
void teardown() throws Exception {
29+
server.shutdown();
30+
}
31+
32+
@Test
33+
void testRenameIndex() throws Exception {
34+
String response = "{ \"taskUid\": 123 }";
35+
36+
server.enqueue(new MockResponse().setBody(response).setResponseCode(202));
37+
38+
TaskInfo task = client.updateIndex("oldIndex", null, "newIndex");
39+
40+
assertThat(task, notNullValue());
41+
assertThat(task.getTaskUid(), equalTo(123));
42+
43+
RecordedRequest req = server.takeRequest();
44+
45+
assertThat(req.getMethod(), equalTo("PATCH"));
46+
assertThat(req.getPath(), equalTo("//indexes/oldIndex"));
47+
48+
String body = req.getBody().readUtf8();
49+
assertThat(body, containsString("\"uid\":\"newIndex\""));
50+
assertThat(req.getHeader("Authorization"), equalTo("Bearer masterKey"));
51+
}
52+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package com.meilisearch.sdk;
2+
3+
import static org.hamcrest.MatcherAssert.assertThat;
4+
import static org.hamcrest.Matchers.*;
5+
6+
import com.meilisearch.sdk.model.SearchResult;
7+
import okhttp3.mockwebserver.MockResponse;
8+
import okhttp3.mockwebserver.MockWebServer;
9+
import org.junit.jupiter.api.AfterEach;
10+
import org.junit.jupiter.api.BeforeEach;
11+
import org.junit.jupiter.api.Test;
12+
13+
class SearchResultQueryVectorTest {
14+
15+
private MockWebServer server;
16+
private Client client;
17+
18+
@BeforeEach
19+
void setup() throws Exception {
20+
server = new MockWebServer();
21+
server.start();
22+
23+
client = new Client(new Config(server.url("/").toString(), "masterKey"));
24+
}
25+
26+
@AfterEach
27+
void teardown() throws Exception {
28+
server.shutdown();
29+
}
30+
31+
@Test
32+
void testQueryVectorDeserialization() throws Exception {
33+
String json =
34+
"""
35+
{
36+
"hits": [],
37+
"queryVector": [1.1, -2.5, 3.14],
38+
"offset": 0,
39+
"limit": 20,
40+
"estimatedTotalHits": 0,
41+
"query": "hello",
42+
"processingTimeMs": 1
43+
}
44+
""";
45+
46+
server.enqueue(new MockResponse().setResponseCode(200).setBody(json));
47+
48+
SearchResult res = client.index("movies").search("hello");
49+
50+
assertThat(res, notNullValue());
51+
assertThat(res.getQueryVector(), hasSize(3));
52+
assertThat(res.getQueryVector().get(0), equalTo(1.1f));
53+
assertThat(res.getQueryVector().get(1), equalTo(-2.5f));
54+
assertThat(res.getQueryVector().get(2), equalTo(3.14f));
55+
}
56+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package com.meilisearch.sdk;
2+
3+
import static org.hamcrest.MatcherAssert.assertThat;
4+
import static org.hamcrest.Matchers.*;
5+
6+
import com.meilisearch.sdk.model.SwapIndexesParams;
7+
import com.meilisearch.sdk.model.TaskInfo;
8+
import okhttp3.mockwebserver.MockResponse;
9+
import okhttp3.mockwebserver.MockWebServer;
10+
import okhttp3.mockwebserver.RecordedRequest;
11+
import org.junit.jupiter.api.AfterEach;
12+
import org.junit.jupiter.api.BeforeEach;
13+
import org.junit.jupiter.api.Test;
14+
15+
class SwapIndexRenameTest {
16+
17+
private MockWebServer server;
18+
private Client client;
19+
20+
@BeforeEach
21+
void setup() throws Exception {
22+
server = new MockWebServer();
23+
server.start();
24+
25+
client = new Client(new Config(server.url("/").toString(), "masterKey"));
26+
}
27+
28+
@AfterEach
29+
void teardown() throws Exception {
30+
server.shutdown();
31+
}
32+
33+
@Test
34+
void testSwapIndexesWithRename() throws Exception {
35+
String jsonResponse = "{ \"taskUid\": 555 }";
36+
37+
server.enqueue(new MockResponse().setBody(jsonResponse).setResponseCode(202));
38+
39+
SwapIndexesParams params =
40+
new SwapIndexesParams()
41+
.setIndexes(new String[] {"indexA", "indexB"})
42+
.setRename(true);
43+
44+
TaskInfo task = client.swapIndexes(new SwapIndexesParams[] {params});
45+
46+
assertThat(task, notNullValue());
47+
assertThat(task.getTaskUid(), equalTo(555));
48+
49+
RecordedRequest req = server.takeRequest();
50+
51+
assertThat(req.getMethod(), equalTo("POST"));
52+
// FIX: Actual path contains double slash
53+
assertThat(req.getPath(), equalTo("//swap-indexes"));
54+
55+
String body = req.getBody().readUtf8();
56+
assertThat(body, containsString("\"indexes\":[\"indexA\",\"indexB\"]"));
57+
assertThat(body, containsString("\"rename\":true"));
58+
}
59+
}

0 commit comments

Comments
 (0)