Skip to content

Commit

Permalink
Merge #652
Browse files Browse the repository at this point in the history
652: Add multi search client method r=curquiza a=jd2024

# Pull Request

## Related issue
Fixes #591

## What does this PR do?
- Add multi search client method

## PR checklist
Please check if your PR fulfills the following requirements:
- [x] Does this PR fix an existing issue, or have you listed the changes applied in the PR description (and why they are needed)?
- [x] Have you read the contributing guidelines?
- [x] Have you made sure that the title is accurate and descriptive of the changes?

Thank you so much for contributing to Meilisearch!


Co-authored-by: Josue Valenzuela <[email protected]>
Co-authored-by: jd2024 <[email protected]>
Co-authored-by: Bruno Casali <[email protected]>
Co-authored-by: Clémentine U. - curqui <[email protected]>
  • Loading branch information
5 people authored Jan 3, 2024
2 parents e736b33 + fd93acd commit 57f25af
Show file tree
Hide file tree
Showing 7 changed files with 201 additions and 2 deletions.
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)));
}
}
}

0 comments on commit 57f25af

Please sign in to comment.