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");
45 changes: 19 additions & 26 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
*/

plugins {
// Apply the java-library plugin to add support for Java Library
id 'java-library'
id 'maven-publish'
id 'signing'
Expand All @@ -24,8 +23,8 @@ base {
}

jacoco {
toolVersion = "0.8.8"
reportsDirectory = layout.buildDirectory.dir("$projectDir/tmp/coverage")
toolVersion = "0.8.8"
reportsDirectory = layout.buildDirectory.dir("$projectDir/tmp/coverage")
}

jacocoTestCoverageVerification {
Expand All @@ -47,23 +46,24 @@ configurations {
}

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

// Use JUnit test framework
// JUnit 6
testImplementation(platform('org.junit:junit-bom:6.0.1'))
testImplementation('org.junit.jupiter:junit-jupiter:6.0.1')
// https://mvnrepository.com/artifact/org.mockito/mockito-core

// Test libs
testImplementation 'org.mockito:mockito-core:4.11.0'
testImplementation 'org.hamcrest:hamcrest:3.0'
testImplementation 'com.squareup.okio:okio:3.16.2'
testImplementation 'com.squareup.okhttp3:okhttp:5.3.0'
testImplementation 'com.squareup.okhttp3:mockwebserver:5.3.0'

testImplementation 'com.fasterxml.jackson.core:jackson-databind:2.20.1'

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

// Lombok
Expand All @@ -72,16 +72,15 @@ dependencies {
testCompileOnly 'org.projectlombok:lombok:1.18.42'
testAnnotationProcessor 'org.projectlombok:lombok:1.18.42'

// Jwt
// JWT
implementation 'com.auth0:java-jwt:4.5.0'
}

task buildJar(type: Jar) {
tasks.register('buildJar', Jar) {
archiveBaseName = 'meilisearch-java'
from {
configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
}
{
} {
exclude 'META-INF/*.SF'
exclude 'META-INF/*.DSA'
exclude 'META-INF/*.RSA'
Expand All @@ -91,11 +90,11 @@ task buildJar(type: Jar) {

test {
useJUnitPlatform {
excludeTags 'integration'
excludeTags 'integration'
}
finalizedBy jacocoTestReport
testLogging {
events 'passed', 'skipped', 'failed'
events 'passed', 'skipped', 'failed'
}
}

Expand All @@ -109,7 +108,7 @@ jacocoTestReport {
finalizedBy jacocoTestCoverageVerification
}

task integrationTest(type: Test) {
tasks.register('integrationTest', Test) {
useJUnitPlatform {
includeTags 'integration'
}
Expand All @@ -128,7 +127,8 @@ java {
}

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

publishing {
Expand Down Expand Up @@ -168,13 +168,10 @@ publishing {
nexusPublishing {
repositories {
sonatype {
// Point to new Central Portal staging API (replaces oss.sonatype.org)
nexusUrl.set(uri("https://ossrh-staging-api.central.sonatype.com/service/local/"))
snapshotRepositoryUrl.set(uri("https://central.sonatype.com/repository/maven-snapshots/"))
// Credentials: use Central Portal token (username/password)
username.set(System.getenv("MAVEN_CENTRAL_USERNAME")) // portal token user
password.set(System.getenv("MAVEN_CENTRAL_PASSWORD")) // portal token password
// packageGroup or stagingProfileId not needed if using nexus-publish-plugin
username.set(System.getenv("MAVEN_CENTRAL_USERNAME"))
password.set(System.getenv("MAVEN_CENTRAL_PASSWORD"))
}
}
}
Expand All @@ -185,17 +182,13 @@ signing {
}

javadoc {
if(JavaVersion.current().isJava9Compatible()) {
if (JavaVersion.current().isJava9Compatible()) {
options.addBooleanOption('html5', true)
}
}

spotless {

java {
// don't need to set target, it is inferred from java

// apply a specific flavor of google-java-format
googleJavaFormat('1.10.0').aosp()
}
}
Expand Down
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
16 changes: 15 additions & 1 deletion src/main/java/com/meilisearch/sdk/IndexesHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
*
* @see <a href="https://www.meilisearch.com/docs/reference/api/indexes">API specification</a>
*/
class IndexesHandler {
public class IndexesHandler {
private final HttpClient httpClient;

/**
Expand Down 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("uid", 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() {}
}
52 changes: 52 additions & 0 deletions src/test/java/com/meilisearch/sdk/IndexRenameTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package com.meilisearch.sdk;

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

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;

class IndexRenameTest {

private MockWebServer server;
private Client client;

@BeforeEach
void setup() throws Exception {
server = new MockWebServer();
server.start();

client = new Client(new Config(server.url("/").toString(), "masterKey"));
}

@AfterEach
void teardown() throws Exception {
server.shutdown();
}

@Test
void testRenameIndex() throws Exception {
String response = "{ \"taskUid\": 123 }";

server.enqueue(new MockResponse().setBody(response).setResponseCode(202));

TaskInfo task = client.updateIndex("oldIndex", null, "newIndex");

assertThat(task, notNullValue());
assertThat(task.getTaskUid(), equalTo(123));

RecordedRequest req = server.takeRequest();

assertThat(req.getMethod(), equalTo("PATCH"));
assertThat(req.getPath(), equalTo("//indexes/oldIndex"));

String body = req.getBody().readUtf8();
assertThat(body, containsString("\"uid\":\"newIndex\""));
assertThat(req.getHeader("Authorization"), equalTo("Bearer masterKey"));
}
}
56 changes: 56 additions & 0 deletions src/test/java/com/meilisearch/sdk/SearchResultQueryVectorTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package com.meilisearch.sdk;

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

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

class SearchResultQueryVectorTest {

private MockWebServer server;
private Client client;

@BeforeEach
void setup() throws Exception {
server = new MockWebServer();
server.start();

client = new Client(new Config(server.url("/").toString(), "masterKey"));
}

@AfterEach
void teardown() throws Exception {
server.shutdown();
}

@Test
void testQueryVectorDeserialization() throws Exception {
String json =
"""
{
"hits": [],
"queryVector": [1.1, -2.5, 3.14],
"offset": 0,
"limit": 20,
"estimatedTotalHits": 0,
"query": "hello",
"processingTimeMs": 1
}
""";

server.enqueue(new MockResponse().setResponseCode(200).setBody(json));

SearchResult res = client.index("movies").search("hello");

assertThat(res, notNullValue());
assertThat(res.getQueryVector(), hasSize(3));
assertThat(res.getQueryVector().get(0), equalTo(1.1f));
assertThat(res.getQueryVector().get(1), equalTo(-2.5f));
assertThat(res.getQueryVector().get(2), equalTo(3.14f));
}
}
59 changes: 59 additions & 0 deletions src/test/java/com/meilisearch/sdk/SwapIndexRenameTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package com.meilisearch.sdk;

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

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;

class SwapIndexRenameTest {

private MockWebServer server;
private Client client;

@BeforeEach
void setup() throws Exception {
server = new MockWebServer();
server.start();

client = new Client(new Config(server.url("/").toString(), "masterKey"));
}

@AfterEach
void teardown() throws Exception {
server.shutdown();
}

@Test
void testSwapIndexesWithRename() throws Exception {
String jsonResponse = "{ \"taskUid\": 555 }";

server.enqueue(new MockResponse().setBody(jsonResponse).setResponseCode(202));

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

TaskInfo task = client.swapIndexes(new SwapIndexesParams[] {params});

assertThat(task, notNullValue());
assertThat(task.getTaskUid(), equalTo(555));

RecordedRequest req = server.takeRequest();

assertThat(req.getMethod(), equalTo("POST"));
// FIX: Actual path contains double slash
assertThat(req.getPath(), equalTo("//swap-indexes"));

String body = req.getBody().readUtf8();
assertThat(body, containsString("\"indexes\":[\"indexA\",\"indexB\"]"));
assertThat(body, containsString("\"rename\":true"));
}
}