Skip to content
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 @@ -21,6 +21,7 @@

import com.carrotsearch.hppc.ObjectHashSet;
import com.carrotsearch.hppc.cursors.ObjectCursor;

import org.apache.logging.log4j.message.ParameterizedMessage;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.DelegatingAnalyzerWrapper;
Expand All @@ -43,6 +44,7 @@
import org.elasticsearch.index.IndexSettings;
import org.elasticsearch.index.IndexSortConfig;
import org.elasticsearch.index.analysis.IndexAnalyzers;
import org.elasticsearch.index.analysis.NamedAnalyzer;
import org.elasticsearch.index.mapper.Mapper.BuilderContext;
import org.elasticsearch.index.query.QueryShardContext;
import org.elasticsearch.index.similarity.SimilarityService;
Expand Down Expand Up @@ -187,6 +189,10 @@ public IndexAnalyzers getIndexAnalyzers() {
return this.indexAnalyzers;
}

public NamedAnalyzer getNamedAnalyzer(String analyzerName) {
return this.indexAnalyzers.get(analyzerName);
}

public DocumentMapperParser documentMapperParser() {
return this.documentParser;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -298,8 +298,7 @@ static SuggestionBuilder<?> fromXContent(XContentParser parser) throws IOExcepti
* Transfers the text, prefix, regex, analyzer, field, size and shard size settings from the
* original {@link SuggestionBuilder} to the target {@link SuggestionContext}
*/
protected void populateCommonFields(MapperService mapperService,
SuggestionSearchContext.SuggestionContext suggestionContext) throws IOException {
protected void populateCommonFields(MapperService mapperService, SuggestionSearchContext.SuggestionContext suggestionContext) {

Objects.requireNonNull(field, "field must not be null");

Expand All @@ -314,7 +313,7 @@ protected void populateCommonFields(MapperService mapperService,
suggestionContext.setAnalyzer(fieldType.searchAnalyzer());
}
} else {
Analyzer luceneAnalyzer = mapperService.getIndexAnalyzers().get(analyzer);
Analyzer luceneAnalyzer = mapperService.getNamedAnalyzer(analyzer);
if (luceneAnalyzer == null) {
throw new IllegalArgumentException("analyzer [" + analyzer + "] doesn't exists");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -412,13 +412,13 @@ public PhraseSuggestionContext.DirectCandidateGenerator build(MapperService mapp
generator.setField(this.field);
transferIfNotNull(this.size, generator::size);
if (this.preFilter != null) {
generator.preFilter(mapperService.getIndexAnalyzers().get(this.preFilter));
generator.preFilter(mapperService.getNamedAnalyzer(this.preFilter));
if (generator.preFilter() == null) {
throw new IllegalArgumentException("Analyzer [" + this.preFilter + "] doesn't exists");
}
}
if (this.postFilter != null) {
generator.postFilter(mapperService.getIndexAnalyzers().get(this.postFilter));
generator.postFilter(mapperService.getNamedAnalyzer(this.postFilter));
if (generator.postFilter() == null) {
throw new IllegalArgumentException("Analyzer [" + this.postFilter + "] doesn't exists");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,7 @@
import org.elasticsearch.index.analysis.TokenFilterFactory;
import org.elasticsearch.index.mapper.MapperService;
import org.elasticsearch.index.query.QueryShardContext;
import org.elasticsearch.script.ExecutableScript;
import org.elasticsearch.script.Script;
import org.elasticsearch.script.ScriptContext;
import org.elasticsearch.script.ScriptType;
import org.elasticsearch.script.TemplateScript;
import org.elasticsearch.search.suggest.SuggestionBuilder;
Expand All @@ -55,7 +53,6 @@
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Set;
import java.util.function.Function;

/**
* Defines the actual suggest command for phrase suggestions ( <tt>phrase</tt>).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@

package org.elasticsearch.search.suggest;

import org.apache.lucene.analysis.core.SimpleAnalyzer;
import org.elasticsearch.Version;
import org.elasticsearch.cluster.metadata.IndexMetaData;
import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
import org.elasticsearch.common.io.stream.Writeable;
import org.elasticsearch.common.settings.Settings;
Expand All @@ -28,15 +31,32 @@
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.Index;
import org.elasticsearch.index.IndexSettings;
import org.elasticsearch.index.analysis.AnalyzerScope;
import org.elasticsearch.index.analysis.NamedAnalyzer;
import org.elasticsearch.index.mapper.MappedFieldType;
import org.elasticsearch.index.mapper.MapperService;
import org.elasticsearch.index.query.QueryShardContext;
import org.elasticsearch.mock.orig.Mockito;
import org.elasticsearch.script.Script;
import org.elasticsearch.script.ScriptService;
import org.elasticsearch.script.TemplateScript;
import org.elasticsearch.search.SearchModule;
import org.elasticsearch.search.suggest.SuggestionSearchContext.SuggestionContext;
import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.test.IndexSettingsModule;
import org.junit.AfterClass;
import org.junit.BeforeClass;

import java.io.IOException;

import static java.util.Collections.emptyList;
import static org.elasticsearch.common.lucene.BytesRefs.toBytesRef;
import static org.elasticsearch.test.EqualsHashCodeTestUtils.checkEqualsAndHashCode;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

public abstract class AbstractSuggestionBuilderTestCase<SB extends SuggestionBuilder<SB>> extends ESTestCase {

Expand All @@ -48,7 +68,7 @@ public abstract class AbstractSuggestionBuilderTestCase<SB extends SuggestionBui
* setup for the whole base test class
*/
@BeforeClass
public static void init() throws IOException {
public static void init() {
SearchModule searchModule = new SearchModule(Settings.EMPTY, false, emptyList());
namedWriteableRegistry = new NamedWriteableRegistry(searchModule.getNamedWriteables());
xContentRegistry = new NamedXContentRegistry(searchModule.getNamedXContents());
Expand Down Expand Up @@ -98,7 +118,7 @@ public static void setCommonPropertiesOnRandomBuilder(SuggestionBuilder<?> rando
/**
* Test equality and hashCode properties
*/
public void testEqualsAndHashcode() throws IOException {
public void testEqualsAndHashcode() {
for (int runs = 0; runs < NUMBER_OF_TESTBUILDERS; runs++) {
checkEqualsAndHashCode(randomTestBuilder(), this::copy, this::mutate);
}
Expand Down Expand Up @@ -131,6 +151,62 @@ public void testFromXContent() throws IOException {
}
}

public void testBuild() throws IOException {
Settings indexSettings = Settings.builder().put(IndexMetaData.SETTING_VERSION_CREATED, Version.CURRENT).build();
IndexSettings idxSettings = IndexSettingsModule.newIndexSettings(new Index(randomAlphaOfLengthBetween(1, 10), "_na_"),
indexSettings);
MapperService mapperService = mock(MapperService.class);
ScriptService scriptService = mock(ScriptService.class);
MappedFieldType fieldType = mockFieldType();
boolean fieldTypeSearchAnalyzerSet = randomBoolean();
if (fieldTypeSearchAnalyzerSet) {
NamedAnalyzer searchAnalyzer = new NamedAnalyzer("fieldSearchAnalyzer", AnalyzerScope.INDEX, new SimpleAnalyzer());
if (Mockito.mockingDetails(fieldType).isMock()) {
when(fieldType.searchAnalyzer()).thenReturn(searchAnalyzer);
} else {
fieldType.setSearchAnalyzer(searchAnalyzer);
}
} else {
when(mapperService.searchAnalyzer())
.thenReturn(new NamedAnalyzer("mapperServiceSearchAnalyzer", AnalyzerScope.INDEX, new SimpleAnalyzer()));
}
when(mapperService.fullName(any(String.class))).thenReturn(fieldType);
when(mapperService.getNamedAnalyzer(any(String.class))).then(
invocation -> new NamedAnalyzer((String) invocation.getArguments()[0], AnalyzerScope.INDEX, new SimpleAnalyzer()));
when(scriptService.compile(any(Script.class), any())).thenReturn(mock(TemplateScript.Factory.class));
QueryShardContext mockShardContext = new QueryShardContext(0, idxSettings, null, null, mapperService, null, scriptService,
xContentRegistry(), null, null, System::currentTimeMillis);

for (int runs = 0; runs < NUMBER_OF_TESTBUILDERS; runs++) {
SB suggestionBuilder = randomTestBuilder();
SuggestionContext suggestionContext = suggestionBuilder.build(mockShardContext);
assertEquals(toBytesRef(suggestionBuilder.text()), suggestionContext.getText());
if (suggestionBuilder.text() != null && suggestionBuilder.prefix() == null) {
assertEquals(toBytesRef(suggestionBuilder.text()), suggestionContext.getPrefix());
} else {
assertEquals(toBytesRef(suggestionBuilder.prefix()), suggestionContext.getPrefix());
}
assertEquals(toBytesRef(suggestionBuilder.regex()), suggestionContext.getRegex());
assertEquals(suggestionBuilder.field(), suggestionContext.getField());
int expectedSize = suggestionBuilder.size() != null ? suggestionBuilder.size : 5;
assertEquals(expectedSize, suggestionContext.getSize());
Integer expectedShardSize = suggestionBuilder.shardSize != null ? suggestionBuilder.shardSize : Math.max(expectedSize, 5);
assertEquals(expectedShardSize, suggestionContext.getShardSize());
assertSame(mockShardContext, suggestionContext.getShardContext());
if (suggestionBuilder.analyzer() != null) {
assertEquals(suggestionBuilder.analyzer(), ((NamedAnalyzer) suggestionContext.getAnalyzer()).name());
} else if (fieldTypeSearchAnalyzerSet){
assertEquals("fieldSearchAnalyzer", ((NamedAnalyzer) suggestionContext.getAnalyzer()).name());
} else {
assertEquals("mapperServiceSearchAnalyzer", ((NamedAnalyzer) suggestionContext.getAnalyzer()).name());
}
}
}

protected MappedFieldType mockFieldType() {
return mock(MappedFieldType.class);
}

/**
* Subclasses can override this method and return a set of fields which should be protected from
* recursive random shuffling in the {@link #testFromXContent()} test case
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,38 +22,49 @@
import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.unit.Fuzziness;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.index.mapper.CompletionFieldMapper.CompletionFieldType;
import org.elasticsearch.index.mapper.MappedFieldType;
import org.elasticsearch.search.suggest.AbstractSuggestionBuilderTestCase;
import org.elasticsearch.search.suggest.completion.context.CategoryQueryContext;
import org.elasticsearch.search.suggest.completion.context.ContextBuilder;
import org.elasticsearch.search.suggest.completion.context.ContextMapping;
import org.elasticsearch.search.suggest.completion.context.ContextMappings;
import org.elasticsearch.search.suggest.completion.context.GeoQueryContext;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class CompletionSuggesterBuilderTests extends AbstractSuggestionBuilderTestCase<CompletionSuggestionBuilder> {

private static final String[] SHUFFLE_PROTECTED_FIELDS = new String[] {CompletionSuggestionBuilder.CONTEXTS_FIELD.getPreferredName()};
private static final String[] SHUFFLE_PROTECTED_FIELDS = new String[] { CompletionSuggestionBuilder.CONTEXTS_FIELD.getPreferredName() };
private static final Map<String, List<? extends ToXContent>> contextMap = new HashMap<>();
private static String categoryContextName;
private static String geoQueryContextName;
private static List<ContextMapping> contextMappings;

@Override
protected CompletionSuggestionBuilder randomSuggestionBuilder() {
return randomCompletionSuggestionBuilder();
}

public static CompletionSuggestionBuilder randomCompletionSuggestionBuilder() {
return randomSuggestionBuilderWithContextInfo().builder;
}

private static class BuilderAndInfo {
CompletionSuggestionBuilder builder;
List<String> catContexts = new ArrayList<>();
List<String> geoContexts = new ArrayList<>();
}

private static BuilderAndInfo randomSuggestionBuilderWithContextInfo() {
final BuilderAndInfo builderAndInfo = new BuilderAndInfo();
// lazy initialization of context names and mappings, cannot be done in init method because other test
// also create random CompletionSuggestionBuilder instances
if (categoryContextName == null) {
categoryContextName = randomAlphaOfLength(10);
}
if (geoQueryContextName == null) {
geoQueryContextName = randomAlphaOfLength(10);
}
if (contextMappings == null) {
contextMappings = Arrays.asList(new ContextMapping[] { ContextBuilder.category(categoryContextName).build(),
ContextBuilder.geo(geoQueryContextName).build() });
}
CompletionSuggestionBuilder testBuilder = new CompletionSuggestionBuilder(randomAlphaOfLengthBetween(2, 20));
setCommonPropertiesOnRandomBuilder(testBuilder);
switch (randomIntBetween(0, 3)) {
Expand All @@ -77,23 +88,18 @@ private static BuilderAndInfo randomSuggestionBuilderWithContextInfo() {
for (int i = 0; i < numContext; i++) {
contexts.add(CategoryQueryContextTests.randomCategoryQueryContext());
}
String name = randomAlphaOfLength(10);
contextMap.put(name, contexts);
builderAndInfo.catContexts.add(name);
contextMap.put(categoryContextName, contexts);
}
if (randomBoolean()) {
int numContext = randomIntBetween(1, 5);
List<GeoQueryContext> contexts = new ArrayList<>(numContext);
for (int i = 0; i < numContext; i++) {
contexts.add(GeoQueryContextTests.randomGeoQueryContext());
}
String name = randomAlphaOfLength(10);
contextMap.put(name, contexts);
builderAndInfo.geoContexts.add(name);
contextMap.put(geoQueryContextName, contexts);
}
testBuilder.contexts(contextMap);
builderAndInfo.builder = testBuilder;
return builderAndInfo;
return testBuilder;
}

/**
Expand Down Expand Up @@ -137,4 +143,11 @@ protected void mutateSpecificParameters(CompletionSuggestionBuilder builder) thr
throw new IllegalStateException("should not through");
}
}

@Override
protected MappedFieldType mockFieldType() {
CompletionFieldType completionFieldType = new CompletionFieldType();
completionFieldType.setContextMappings(new ContextMappings(contextMappings));
return completionFieldType;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ protected void mutateSpecificParameters(PhraseSuggestionBuilder builder) throws
}
}

public void testInvalidParameters() throws IOException {
public void testInvalidParameters() {
// test missing field name
Exception e = expectThrows(NullPointerException.class, () -> new PhraseSuggestionBuilder((String) null));
assertEquals("suggestion requires a field name", e.getMessage());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ protected void mutateSpecificParameters(TermSuggestionBuilder builder) throws IO
}
}

public void testInvalidParameters() throws IOException {
public void testInvalidParameters() {
// test missing field name
Exception e = expectThrows(NullPointerException.class, () -> new TermSuggestionBuilder((String) null));
assertEquals("suggestion requires a field name", e.getMessage());
Expand Down