Skip to content
Open
Show file tree
Hide file tree
Changes from 8 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("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() {}
}
53 changes: 53 additions & 0 deletions src/test/java/com/meilisearch/sdk/IndexRenameTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
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"));
// FIX: Actual path includes double slash
assertThat(req.getPath(), equalTo("//indexes/oldIndex"));

String body = req.getBody().readUtf8();
assertThat(body, containsString("\"indexUid\":\"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"));
}
}