Commit ac83ba97 authored by Jean-Baptiste Nizet's avatar Jean-Baptiste Nizet Committed by Exbrayat Cédric
Browse files

feat: remove suggestions that differ from a previous one only by case

parent 79214043
...@@ -32,7 +32,7 @@ public interface GeneticResourceDaoCustom { ...@@ -32,7 +32,7 @@ public interface GeneticResourceDaoCustom {
/** /**
* Suggests completions for the given term. It autocompletes all the fields except the identifier, the URL and * Suggests completions for the given term. It autocompletes all the fields except the identifier, the URL and
* numeric fields, and the description. * numeric fields, and the description.
* @return The N first distinct suggested completions * @return The 10 first suggested completions
*/ */
List<String> suggest(String term); List<String> suggest(String term);
......
...@@ -4,8 +4,10 @@ import static org.elasticsearch.index.query.QueryBuilders.*; ...@@ -4,8 +4,10 @@ import static org.elasticsearch.index.query.QueryBuilders.*;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.TreeSet;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
...@@ -68,6 +70,11 @@ public class GeneticResourceDaoImpl implements GeneticResourceDaoCustom { ...@@ -68,6 +70,11 @@ public class GeneticResourceDaoImpl implements GeneticResourceDaoCustom {
"countryOfCollect" "countryOfCollect"
).collect(Collectors.toSet())); ).collect(Collectors.toSet()));
/**
* The max number of suggestions returned to the caller
*/
private int MAX_RETURNED_SUGGESTION_COUNT = 10;
private final ElasticsearchTemplate elasticsearchTemplate; private final ElasticsearchTemplate elasticsearchTemplate;
public GeneticResourceDaoImpl(ElasticsearchTemplate elasticsearchTemplate) { public GeneticResourceDaoImpl(ElasticsearchTemplate elasticsearchTemplate) {
...@@ -114,11 +121,13 @@ public class GeneticResourceDaoImpl implements GeneticResourceDaoCustom { ...@@ -114,11 +121,13 @@ public class GeneticResourceDaoImpl implements GeneticResourceDaoCustom {
@Override @Override
public List<String> suggest(String term) { public List<String> suggest(String term) {
SuggestBuilder suggestion = SuggestBuilder suggestion =
new SuggestBuilder().addSuggestion(COMPLETION, new SuggestBuilder().addSuggestion(
SuggestBuilders.completionSuggestion(SUGGESTIONS_FIELD) COMPLETION,
.text(term) SuggestBuilders.completionSuggestion(SUGGESTIONS_FIELD)
.size(8) .text(term)
.skipDuplicates(true)); .size(MAX_RETURNED_SUGGESTION_COUNT * 2) // because we deduplicate case-differing
// suggestions after
.skipDuplicates(true));
Client client = elasticsearchTemplate.getClient(); Client client = elasticsearchTemplate.getClient();
String index = elasticsearchTemplate.getPersistentEntityFor(GeneticResource.class).getIndexName(); String index = elasticsearchTemplate.getPersistentEntityFor(GeneticResource.class).getIndexName();
...@@ -129,13 +138,28 @@ public class GeneticResourceDaoImpl implements GeneticResourceDaoCustom { ...@@ -129,13 +138,28 @@ public class GeneticResourceDaoImpl implements GeneticResourceDaoCustom {
.setFetchSource(false) // avoid getting the source documents, which are useless .setFetchSource(false) // avoid getting the source documents, which are useless
.get(); .get();
return response.getSuggest() List<String> suggestions = response.getSuggest()
.getSuggestion(COMPLETION) .getSuggestion(COMPLETION)
.getEntries() .getEntries()
.stream() .stream()
.flatMap(entry -> entry.getOptions().stream()) .flatMap(entry -> entry.getOptions().stream())
.map(option -> option.getText().string()) .map(option -> option.getText().string())
.collect(Collectors.toList()); .collect(Collectors.toList());
return removeSuggestionsDifferingByCase(suggestions);
}
private List<String> removeSuggestionsDifferingByCase(List<String> suggestions) {
// Use a TreeSet with case insensitive order to only keep unique values, ignoring case
TreeSet<String> distinctSuggestions = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
distinctSuggestions.addAll(suggestions);
// Copy the remaining values to a HashSet, comparing by equality
Set<String> remainingSuggestions = new HashSet<>(distinctSuggestions);
// keep max 10 suggestions, in the original order, but only keep those which are equal one of the remaining
// suggestions
return suggestions.stream().filter(remainingSuggestions::contains).limit(MAX_RETURNED_SUGGESTION_COUNT).collect(Collectors.toList());
} }
@Override @Override
......
...@@ -5,6 +5,7 @@ import static org.assertj.core.api.Assertions.assertThat; ...@@ -5,6 +5,7 @@ import static org.assertj.core.api.Assertions.assertThat;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.TreeSet;
import java.util.UUID; import java.util.UUID;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
...@@ -278,6 +279,38 @@ class GeneticResourceDaoTest { ...@@ -278,6 +279,38 @@ class GeneticResourceDaoTest {
assertThat(result).containsOnly("vitis vinifera"); assertThat(result).containsOnly("vitis vinifera");
} }
@Test
public void shouldRemoveCaseDifferingResults() {
GeneticResource resource =
new GeneticResourceBuilder()
.withId(UUID.randomUUID().toString())
.withName("vita")
.build();
GeneticResource resource2 =
new GeneticResourceBuilder()
.withId(UUID.randomUUID().toString())
.withName("vitis")
.build();
GeneticResource resource3 =
new GeneticResourceBuilder()
.withId(UUID.randomUUID().toString())
.withName("VITIS")
.build();
geneticResourceDao.saveAll(Arrays.asList(new IndexedGeneticResource(resource),
new IndexedGeneticResource(resource2),
new IndexedGeneticResource(resource3)));
List<String> result = geneticResourceDao.suggest("vit");
assertThat(result).hasSize(2);
TreeSet<String> ignoringCaseSet = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
ignoringCaseSet.addAll(result);
assertThat(ignoringCaseSet).hasSize(2);
}
private void shouldSearch(BiConsumer<GeneticResourceBuilder, String> config) { private void shouldSearch(BiConsumer<GeneticResourceBuilder, String> config) {
GeneticResourceBuilder geneticResourceBuilder = new GeneticResourceBuilder(); GeneticResourceBuilder geneticResourceBuilder = new GeneticResourceBuilder();
config.accept(geneticResourceBuilder, "foo bar baz"); config.accept(geneticResourceBuilder, "foo bar baz");
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment