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

fix(specs): make the searchParams compatible with v4 [skip-bc] #4108

Merged
merged 7 commits into from
Nov 15, 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
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
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
Loading