Skip to content

Commit

Permalink
fix(specs): make the searchParams compatible with v4 [skip-bc] (#4108)
Browse files Browse the repository at this point in the history
  • Loading branch information
millotp authored Nov 15, 2024
1 parent 1ed8dad commit 36d583e
Show file tree
Hide file tree
Showing 13 changed files with 279 additions and 259 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,6 @@ public fun SearchForHits.Companion.from(
replaceSynonymsInHighlight = searchParamsObject.replaceSynonymsInHighlight,
minProximity = searchParamsObject.minProximity,
responseFields = searchParamsObject.responseFields,
maxFacetHits = searchParamsObject.maxFacetHits,
maxValuesPerFacet = searchParamsObject.maxValuesPerFacet,
sortFacetValuesBy = searchParamsObject.sortFacetValuesBy,
attributeCriteriaComputedByMinProximity = searchParamsObject.attributeCriteriaComputedByMinProximity,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,6 @@ public extension SearchForHits {
self.replaceSynonymsInHighlight = searchParamsObject.replaceSynonymsInHighlight
self.minProximity = searchParamsObject.minProximity
self.responseFields = searchParamsObject.responseFields
self.maxFacetHits = searchParamsObject.maxFacetHits
self.maxValuesPerFacet = searchParamsObject.maxValuesPerFacet
self.sortFacetValuesBy = searchParamsObject.sortFacetValuesBy
self.attributeCriteriaComputedByMinProximity = searchParamsObject.attributeCriteriaComputedByMinProximity
Expand Down Expand Up @@ -175,7 +174,6 @@ public extension SearchForFacets {
self.replaceSynonymsInHighlight = searchParamsObject.replaceSynonymsInHighlight
self.minProximity = searchParamsObject.minProximity
self.responseFields = searchParamsObject.responseFields
self.maxFacetHits = searchParamsObject.maxFacetHits
self.maxValuesPerFacet = searchParamsObject.maxValuesPerFacet
self.sortFacetValuesBy = searchParamsObject.sortFacetValuesBy
self.attributeCriteriaComputedByMinProximity = searchParamsObject.attributeCriteriaComputedByMinProximity
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

import com.algolia.codegen.exceptions.*;
import com.algolia.codegen.utils.*;
import com.google.common.collect.ImmutableMap.Builder;
import com.samskivert.mustache.Mustache;
import com.samskivert.mustache.Mustache.Lambda;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.Operation;
import io.swagger.v3.oas.models.servers.Server;
Expand Down Expand Up @@ -156,4 +158,24 @@ public Map<String, ModelsMap> postProcessAllModels(Map<String, ModelsMap> objs)
public CodegenOperation fromOperation(String path, String httpMethod, Operation operation, List<Server> servers) {
return Helpers.specifyCustomRequest(super.fromOperation(path, httpMethod, operation, servers));
}

/** Convert a Seq type to a valid class name. */
private String typeToName(String content) {
// for dictionary, remove the key type
String[] parts = content.replace("string, ", "").split("<");
String name = "";
for (int i = 0; i < parts.length; i++) {
name += Helpers.capitalize(parts[i].replace(">", "").replace(",", "").replace(" ", ""));
}
return name;
}

@Override
protected Builder<String, Lambda> addMustacheLambdas() {
Builder<String, Lambda> lambdas = super.addMustacheLambdas();

lambdas.put("type-to-name", (Mustache.Lambda) (fragment, writer) -> writer.write(typeToName(fragment.execute())));

return lambdas;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,14 @@ public class AlgoliaSwiftGenerator extends Swift5ClientCodegen {
"highlightresultoption",
"ignoreplurals",
"indexsettingsassearchparams",
"insideboundingbox",
"languages",
"matchedgeolocation",
"matchlevel",
"mode",
"numericfilters",
"optionalfilters",
"optionalwords",
"params",
"personalization",
"promote",
Expand Down
43 changes: 19 additions & 24 deletions playground/java/src/main/java/com/algolia/playground/Insights.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,36 +5,31 @@
import com.algolia.config.LogLevel;
import com.algolia.model.insights.ClickEvent;
import com.algolia.model.insights.ClickedObjectIDs;
import com.algolia.model.insights.EventsItems;
import com.algolia.model.insights.InsightsEvents;
import io.github.cdimascio.dotenv.Dotenv;

import java.util.List;

public class Insights {

public static void main(String[] args) throws Exception {
var dotenv = Dotenv.configure().directory("../").load();
var appId = dotenv.get("ALGOLIA_APPLICATION_ID");
var apiKey = dotenv.get("ALGOLIA_SEARCH_KEY");
var indexName = dotenv.get("SEARCH_INDEX");
public static void main(String[] args) throws Exception {
var dotenv = Dotenv.configure().directory("../").load();
var appId = dotenv.get("ALGOLIA_APPLICATION_ID");
var apiKey = dotenv.get("ALGOLIA_SEARCH_KEY");
var indexName = dotenv.get("SEARCH_INDEX");

var options = new ClientOptions.Builder()
.addAlgoliaAgentSegment("Playground")
.setLogLevel(LogLevel.BODY)
.build();
var options = new ClientOptions.Builder().addAlgoliaAgentSegment("Playground").setLogLevel(LogLevel.BODY).build();

var client = new InsightsClient(appId, apiKey, options);
var params = new InsightsEvents();
var event = new ClickedObjectIDs()
.setEventType(ClickEvent.CLICK)
.setUserToken("user")
.setIndex(indexName)
.setObjectIDs(List.of("id123"))
.setEventName("click");
params.addEvents(event);
var result = client.pushEvents(params);
System.out.println(result);
client.close();
}
var client = new InsightsClient(appId, apiKey, options);
var params = new InsightsEvents();
var event = new ClickedObjectIDs()
.setEventType(ClickEvent.CLICK)
.setUserToken("user")
.setIndex(indexName)
.setObjectIDs(List.of("id123"))
.setEventName("click");
params.addEvents(event);
var result = client.pushEvents(params);
System.out.println(result);
client.close();
}
}
121 changes: 58 additions & 63 deletions playground/java/src/main/java/com/algolia/playground/Search.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,90 +2,85 @@

import com.algolia.api.SearchClient;
import com.algolia.config.ClientOptions;
import com.algolia.config.LogLevel;
import com.algolia.model.search.*;
import io.github.cdimascio.dotenv.Dotenv;

import java.util.Arrays;
import java.util.List;
import java.util.Map;

class Actor extends Hit {

public String name;
public String name;

public Actor() {
}
public Actor() {}

public Actor(String name) {
this.name = name;
}
public Actor(String name) {
this.name = name;
}
}

public class Search {

public static void main(String[] args) throws Exception {
var dotenv = Dotenv.configure().directory("../").load();
var appId = dotenv.get("ALGOLIA_APPLICATION_ID");
var apiKey = dotenv.get("ALGOLIA_ADMIN_KEY");
var indexName = dotenv.get("SEARCH_INDEX");
var query = dotenv.get("SEARCH_QUERY");
public static void main(String[] args) throws Exception {
var dotenv = Dotenv.configure().directory("../").load();
var appId = dotenv.get("ALGOLIA_APPLICATION_ID");
var apiKey = dotenv.get("ALGOLIA_ADMIN_KEY");
var indexName = dotenv.get("SEARCH_INDEX");
var query = dotenv.get("SEARCH_QUERY");

var options = new ClientOptions.Builder()
.addAlgoliaAgentSegment("Playground", "1.0.0")
//.setLogLevel(LogLevel.BODY)
.build();
var options = new ClientOptions.Builder()
.addAlgoliaAgentSegment("Playground", "1.0.0")
// .setLogLevel(LogLevel.BODY)
.build();

var client = new SearchClient(appId, apiKey, options);
var records = Arrays.asList(new Actor("Tom Cruise"), new Actor("Scarlett Johansson"));
var batch = records.stream()
.map(entry -> new BatchRequest().setAction(Action.ADD_OBJECT).setBody(entry))
.toList();
var response = client.batch(indexName, new BatchWriteParams().setRequests(batch));
client.waitForTask(indexName, response.getTaskID());
var client = new SearchClient(appId, apiKey, options);
var records = Arrays.asList(new Actor("Tom Cruise"), new Actor("Scarlett Johansson"));
var batch = records.stream().map(entry -> new BatchRequest().setAction(Action.ADD_OBJECT).setBody(entry)).toList();
var response = client.batch(indexName, new BatchWriteParams().setRequests(batch));
client.waitForTask(indexName, response.getTaskID());

var browse = client.browseObjects(indexName, new BrowseParamsObject().setQuery("tom"), Actor.class);
System.out.println("-> Browse Objects:");
for (var hit : browse) {
System.out.println("> " + hit.name);
}

singleSearch(client, indexName, query);
multiSearch(indexName, query, client);
client.close();
var browse = client.browseObjects(indexName, new BrowseParamsObject().setQuery("tom"), Actor.class);
System.out.println("-> Browse Objects:");
for (var hit : browse) {
System.out.println("> " + hit.name);
}

private static void singleSearch(SearchClient client, String indexName, String query) {
SearchParamsObject params = new SearchParamsObject()
.setQuery(query)
.setAroundPrecision(AroundPrecision.of(1000))
.setAroundRadius(AroundRadiusAll.ALL);
SearchResponse<Actor> actorSearchResponse = client.searchSingleIndex(indexName, params, Actor.class);
System.out.println("-> Single Index Search:");
for (var hit : actorSearchResponse.getHits()) {
System.out.println("> " + hit.name);
}
singleSearch(client, indexName, query);
multiSearch(indexName, query, client);
client.close();
}

private static void singleSearch(SearchClient client, String indexName, String query) {
SearchParamsObject params = new SearchParamsObject()
.setQuery(query)
.setAroundPrecision(AroundPrecision.of(1000))
.setAroundRadius(AroundRadiusAll.ALL);
SearchResponse<Actor> actorSearchResponse = client.searchSingleIndex(indexName, params, Actor.class);
System.out.println("-> Single Index Search:");
for (var hit : actorSearchResponse.getHits()) {
System.out.println("> " + hit.name);
}
}

private static void multiSearch(String indexName, String query, SearchClient client) {
var searchMethodParams = new SearchMethodParams();
var searchQuery = new SearchForHits()
.setIndexName(indexName)
.setQuery(query)
.addAttributesToSnippet("title")
.addAttributesToSnippet("alternative_titles");
List<SearchQuery> requests = List.of(searchQuery);
searchMethodParams.setRequests(requests);
private static void multiSearch(String indexName, String query, SearchClient client) {
var searchMethodParams = new SearchMethodParams();
var searchQuery = new SearchForHits()
.setIndexName(indexName)
.setQuery(query)
.addAttributesToSnippet("title")
.addAttributesToSnippet("alternative_titles");
List<SearchQuery> requests = List.of(searchQuery);
searchMethodParams.setRequests(requests);

var responses = client.search(searchMethodParams, Actor.class);
var results = responses.getResults();
System.out.println("-> Multi Index Search:");
for (var result : results) {
var response = (SearchResponse) result;
for (var hit : response.getHits()) {
var record = (Map) hit;
System.out.println("> " + record.get("name"));
}
}
var responses = client.search(searchMethodParams, Actor.class);
var results = responses.getResults();
System.out.println("-> Multi Index Search:");
for (var result : results) {
var response = (SearchResponse) result;
for (var hit : response.getHits()) {
var record = (Map) hit;
System.out.println("> " + record.get("name"));
}
}
}
}
67 changes: 38 additions & 29 deletions specs/common/schemas/IndexSettings.yml
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,8 @@ baseIndexSettings:
This applies faceting _after_ deduplication, which will result in accurate facet counts.
example: url
type: string
maxFacetHits:
$ref: '#/maxFacetHits'

indexSettingsAsSearchParams:
type: object
Expand Down Expand Up @@ -570,33 +572,7 @@ indexSettingsAsSearchParams:
x-categories:
- Query strategy
optionalWords:
type: array
items:
type: string
example:
- blue
- iphone case
description: |
Words that should be considered optional when found in the query.
By default, records must match all words in the search query to be included in the search results.
Adding optional words can help to increase the number of search results by running an additional search query that doesn't include the optional words.
For example, if the search query is "action video" and "video" is an optional word,
the search engine runs two queries. One for "action video" and one for "action".
Records that match all words are ranked higher.
For a search query with 4 or more words **and** all its words are optional,
the number of matched words required for a record to be included in the search results increases for every 1,000 records:
- If `optionalWords` has less than 10 words, the required number of matched words increases by 1:
results 1 to 1,000 require 1 matched word, results 1,001 to 2000 need 2 matched words.
- If `optionalWords` has 10 or more words, the number of required matched words increases by the number of optional words divided by 5 (rounded down).
For example, with 18 optional words: results 1 to 1,000 require 1 matched word, results 1,001 to 2000 need 4 matched words.
For more information, see [Optional words](https://www.algolia.com/doc/guides/managing-results/optimize-search-results/empty-or-insufficient-results/#creating-a-list-of-optional-words).
default: []
x-categories:
- Query strategy
$ref: '#/optionalWords'
disableExactOnAttributes:
type: array
items:
Expand Down Expand Up @@ -708,8 +684,6 @@ indexSettingsAsSearchParams:
default: ['*']
x-categories:
- Advanced
maxFacetHits:
$ref: '#/maxFacetHits'
maxValuesPerFacet:
type: integer
description: Maximum number of facet values to return for each facet.
Expand Down Expand Up @@ -1238,3 +1212,38 @@ booleanString:
enum:
- 'true'
- 'false'

optionalWords:
oneOf:
- type: string
- type: 'null'
- $ref: '#/optionalWordsArray'

optionalWordsArray:
type: array
items:
type: string
example:
- blue
- iphone case
description: |
Words that should be considered optional when found in the query.
By default, records must match all words in the search query to be included in the search results.
Adding optional words can help to increase the number of search results by running an additional search query that doesn't include the optional words.
For example, if the search query is "action video" and "video" is an optional word,
the search engine runs two queries. One for "action video" and one for "action".
Records that match all words are ranked higher.
For a search query with 4 or more words **and** all its words are optional,
the number of matched words required for a record to be included in the search results increases for every 1,000 records:
- If `optionalWords` has less than 10 words, the required number of matched words increases by 1:
results 1 to 1,000 require 1 matched word, results 1,001 to 2000 need 2 matched words.
- If `optionalWords` has 10 or more words, the number of required matched words increases by the number of optional words divided by 5 (rounded down).
For example, with 18 optional words: results 1 to 1,000 require 1 matched word, results 1,001 to 2000 need 4 matched words.
For more information, see [Optional words](https://www.algolia.com/doc/guides/managing-results/optimize-search-results/empty-or-insufficient-results/#creating-a-list-of-optional-words).
default: []
x-categories:
- Query strategy
6 changes: 6 additions & 0 deletions specs/common/schemas/SearchParams.yml
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,12 @@ aroundLatLngViaIP:
- Geo-Search

insideBoundingBox:
oneOf:
- type: string
- type: 'null'
- $ref: '#/insideBoundingBoxArray'

insideBoundingBoxArray:
type: array
items:
type: array
Expand Down
Loading

0 comments on commit 36d583e

Please sign in to comment.