Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add multi search client method #652

Merged
merged 9 commits into from
Jan 3, 2024
Merged
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
7 changes: 7 additions & 0 deletions .code-samples.meilisearch.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -749,3 +749,10 @@ async_guide_filter_by_index_uids_1: |-
async_guide_canceled_by_1: |-
TasksQuery query = new TasksQuery().setCanceledBy(new int[] {9, 15});
client.getTasks(query);
multi_search_1: |-
MultiSearchRequest multiSearchRequest = new MultiSearchRequest();
multiIndexSearch.addQuery(new IndexSearchRequest("movies").setQuery("pooh").setLimit(5));
multiIndexSearch.addQuery(new IndexSearchRequest("movies").setQuery("nemo").setLimit(5));
multiIndexSearch.addQuery(new IndexSearchRequest("movie_ratings").setQuery("us"));

client.multiSearch(multiSearchRequest);
7 changes: 7 additions & 0 deletions src/main/java/com/meilisearch/sdk/Client.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import com.meilisearch.sdk.model.Key;
import com.meilisearch.sdk.model.KeyUpdate;
import com.meilisearch.sdk.model.KeysQuery;
import com.meilisearch.sdk.model.MultiSearchResult;
import com.meilisearch.sdk.model.Results;
import com.meilisearch.sdk.model.Stats;
import com.meilisearch.sdk.model.SwapIndexesParams;
Expand Down Expand Up @@ -427,6 +428,12 @@ public void deleteKey(String key) throws MeilisearchException {
this.keysHandler.deleteKey(key);
}

public Results<MultiSearchResult> multiSearch(MultiSearchRequest search)
throws MeilisearchException {
return this.config.httpClient.post(
"/multi-search", search, Results.class, MultiSearchResult.class);
}

public String generateTenantToken(String apiKeyUid, Map<String, Object> searchRules)
throws MeilisearchException {
return this.generateTenantToken(apiKeyUid, searchRules, new TenantTokenOptions());
Expand Down
5 changes: 3 additions & 2 deletions src/main/java/com/meilisearch/sdk/HttpClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -90,10 +90,11 @@ <T> T get(String api, String param, Class<T> targetClass, Class<?>... parameters
* @return results of the search
* @throws MeilisearchException if the response is an error
*/
<S, T> T post(String api, S body, Class<T> targetClass) throws MeilisearchException {
<S, T> T post(String api, S body, Class<T> targetClass, Class<?>... parameters)
throws MeilisearchException {
HttpRequest requestConfig = request.create(HttpMethod.POST, api, this.headers, body);
HttpResponse<T> httpRequest = this.client.post(requestConfig);
HttpResponse<T> httpResponse = response.create(httpRequest, targetClass);
HttpResponse<T> httpResponse = response.create(httpRequest, targetClass, parameters);

if (httpResponse.getStatusCode() >= 400) {
throw new MeilisearchApiException(
Expand Down
96 changes: 96 additions & 0 deletions src/main/java/com/meilisearch/sdk/IndexSearchRequest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package com.meilisearch.sdk;

import com.meilisearch.sdk.model.MatchingStrategy;
import lombok.*;
import lombok.experimental.Accessors;
import org.json.JSONObject;

@Builder
@AllArgsConstructor(access = AccessLevel.PACKAGE)
@NoArgsConstructor(access = AccessLevel.PACKAGE)
@Getter
@Setter
@Accessors(chain = true)
public class IndexSearchRequest {
private String indexUid;
private String q;
private Integer offset;
private Integer limit;
private String[] attributesToRetrieve;
private String[] attributesToCrop;
private Integer cropLength;
private String cropMarker;
private String highlightPreTag;
private String highlightPostTag;
private MatchingStrategy matchingStrategy;
private String[] attributesToHighlight;
private String[] filter;
private String[][] filterArray;
private Boolean showMatchesPosition;
private String[] facets;
private String[] sort;
protected Integer page;
protected Integer hitsPerPage;
protected Boolean showRankingScore;

/**
* Constructor for MultiSearchRequest for building search queries with the default values:
* offset: 0, limit: 20, attributesToRetrieve: ["*"], attributesToCrop: null, cropLength: 200,
* attributesToHighlight: null, filter: null, showMatchesPosition: false, facets: null, sort:
* null
*
* @param indexUid uid of the requested index String
*/
public IndexSearchRequest(String indexUid) {
this();
this.indexUid = indexUid;
}

/**
* Method to set the Query String
*
* <p>This method is an alias of setQ()
*
* @param q Query String
* @return SearchRequest
*/
public IndexSearchRequest setQuery(String q) {
return setQ(q);
}

/**
* Method that returns the JSON String of the SearchRequest
*
* @return JSON String of the SearchRequest query
*/
@Override
public String toString() {
JSONObject jsonObject =
new JSONObject()
.put("q", this.q)
.put("offset", this.offset)
.put("limit", this.limit)
.put("attributesToRetrieve", this.attributesToRetrieve)
.put("cropLength", this.cropLength)
.put("cropMarker", this.cropMarker)
.put("highlightPreTag", this.highlightPreTag)
.put("highlightPostTag", this.highlightPostTag)
.put(
"matchingStrategy",
this.matchingStrategy == null
? null
: this.matchingStrategy.toString())
.put("showMatchesPosition", this.showMatchesPosition)
.put("facets", this.facets)
.put("sort", this.sort)
.put("page", this.page)
.put("hitsPerPage", this.hitsPerPage)
.putOpt("attributesToCrop", this.attributesToCrop)
.putOpt("attributesToHighlight", this.attributesToHighlight)
.putOpt("filter", this.filter)
.putOpt("filter", this.filterArray)
.putOpt("showRankingScore", this.showRankingScore);

return jsonObject.toString();
}
}
23 changes: 23 additions & 0 deletions src/main/java/com/meilisearch/sdk/MultiSearchRequest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.meilisearch.sdk;

import java.util.ArrayList;
import lombok.*;

public class MultiSearchRequest {
private ArrayList<IndexSearchRequest> queries;

public MultiSearchRequest() {
this.queries = new ArrayList();
}

/**
* Method to add new Query
*
* @param search Query IndexSearchRequest
* @return MultiSearchRequest
*/
public MultiSearchRequest addQuery(IndexSearchRequest search) {
this.queries.add(search);
return this;
}
}
26 changes: 26 additions & 0 deletions src/main/java/com/meilisearch/sdk/model/MultiSearchResult.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.meilisearch.sdk.model;

import java.util.ArrayList;
import java.util.HashMap;
import lombok.Getter;
import lombok.ToString;

/**
* Multi search response
*
* <p>https://www.meilisearch.com/docs/reference/api/multi_search#response
*/
@Getter
@ToString
public class MultiSearchResult implements Searchable {
String indexUid;
ArrayList<HashMap<String, Object>> hits;
Object facetDistribution;
int processingTimeMs;
String query;
int offset;
int limit;
int estimatedTotalHits;

public MultiSearchResult() {}
}
39 changes: 39 additions & 0 deletions src/test/java/com/meilisearch/integration/SearchTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,19 @@
import com.meilisearch.integration.classes.AbstractIT;
import com.meilisearch.integration.classes.TestData;
import com.meilisearch.sdk.Index;
import com.meilisearch.sdk.IndexSearchRequest;
import com.meilisearch.sdk.MultiSearchRequest;
import com.meilisearch.sdk.SearchRequest;
import com.meilisearch.sdk.json.GsonJsonHandler;
import com.meilisearch.sdk.model.MatchingStrategy;
import com.meilisearch.sdk.model.MultiSearchResult;
import com.meilisearch.sdk.model.SearchResult;
import com.meilisearch.sdk.model.SearchResultPaginated;
import com.meilisearch.sdk.model.Searchable;
import com.meilisearch.sdk.model.Settings;
import com.meilisearch.sdk.model.TaskInfo;
import com.meilisearch.sdk.utils.Movie;
import java.util.HashSet;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Tag;
Expand Down Expand Up @@ -643,4 +647,39 @@ public void testPlaceHolderWithLimit() throws Exception {

assertThat(searchResult.getHits(), hasSize(10));
}

@Test
public void testMultiSearch() throws Exception {
HashSet<String> indexUids = new HashSet();
indexUids.add("MultiSearch1");
indexUids.add("MultiSearch2");

for (String indexUid : indexUids) {
Index index = client.index(indexUid);

TestData<Movie> testData = this.getTestData(MOVIES_INDEX, Movie.class);
TaskInfo task = index.addDocuments(testData.getRaw());

index.waitForTask(task.getTaskUid());
}

MultiSearchRequest search = new MultiSearchRequest();

for (String indexUid : indexUids) {
search.addQuery(new IndexSearchRequest(indexUid).setQuery("batman"));
}

MultiSearchResult[] results = client.multiSearch(search).getResults();

assertThat(results.length, is(2));

for (MultiSearchResult searchResult : results) {
assertThat(indexUids.contains(searchResult.getIndexUid()), is(true));
assertThat(searchResult.getFacetDistribution(), is(nullValue()));
assertThat(searchResult.getHits(), hasSize(1));
assertThat(searchResult.getOffset(), is(equalTo(0)));
assertThat(searchResult.getLimit(), is(equalTo(20)));
assertThat(searchResult.getEstimatedTotalHits(), is(equalTo(1)));
}
}
}