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

Distinguish between simple matches with and without the terms index #63945

Merged
merged 8 commits into from
Oct 27, 2020
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ public static final class ScaledFloatFieldType extends SimpleMappedFieldType {

public ScaledFloatFieldType(String name, boolean indexed, boolean stored, boolean hasDocValues,
Map<String, String> meta, double scalingFactor, Double nullValue) {
super(name, indexed, stored, hasDocValues, TextSearchInfo.SIMPLE_MATCH_ONLY, meta);
super(name, indexed, stored, hasDocValues, TextSearchInfo.SIMPLE_MATCH_WITHOUT_TERMS, meta);
this.scalingFactor = scalingFactor;
this.nullValue = nullValue;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -556,15 +556,9 @@ public void testScriptCaching() throws Exception {
ScriptHeuristic scriptHeuristic = new ScriptHeuristic(
new Script(ScriptType.INLINE, "mockscript", "Math.random()", Collections.emptyMap())
);
boolean useSigText = randomBoolean();
SearchResponse r;
if (useSigText) {
r = client().prepareSearch("cache_test_idx").setSize(0)
.addAggregation(significantText("foo", "s").significanceHeuristic(scriptHeuristic)).get();
} else {
r = client().prepareSearch("cache_test_idx").setSize(0)
.addAggregation(significantTerms("foo").field("s").significanceHeuristic(scriptHeuristic)).get();
}
r = client().prepareSearch("cache_test_idx").setSize(0)
.addAggregation(significantTerms("foo").field("s").significanceHeuristic(scriptHeuristic)).get();
assertSearchResponse(r);

assertThat(client().admin().indices().prepareStats("cache_test_idx").setRequestCache(true).get().getTotal().getRequestCache()
Expand All @@ -574,14 +568,8 @@ public void testScriptCaching() throws Exception {

// Test that a request using a deterministic script gets cached
scriptHeuristic = getScriptSignificanceHeuristic();
useSigText = randomBoolean();
if (useSigText) {
r = client().prepareSearch("cache_test_idx").setSize(0)
.addAggregation(significantText("foo", "s").significanceHeuristic(scriptHeuristic)).get();
} else {
r = client().prepareSearch("cache_test_idx").setSize(0)
.addAggregation(significantTerms("foo").field("s").significanceHeuristic(scriptHeuristic)).get();
}
r = client().prepareSearch("cache_test_idx").setSize(0)
.addAggregation(significantTerms("foo").field("s").significanceHeuristic(scriptHeuristic)).get();
assertSearchResponse(r);

assertThat(client().admin().indices().prepareStats("cache_test_idx").setRequestCache(true).get().getTotal().getRequestCache()
Expand All @@ -590,11 +578,7 @@ public void testScriptCaching() throws Exception {
.getMissCount(), equalTo(1L));

// Ensure that non-scripted requests are cached as normal
if (useSigText) {
r = client().prepareSearch("cache_test_idx").setSize(0).addAggregation(significantText("foo", "s")).get();
} else {
r = client().prepareSearch("cache_test_idx").setSize(0).addAggregation(significantTerms("foo").field("s")).get();
}
r = client().prepareSearch("cache_test_idx").setSize(0).addAggregation(significantTerms("foo").field("s")).get();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't we lose coverage with these changes?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, you're right, I had thought this was just testing a useless agg but actually I should change it instead to also have some text and to run the sigText agg over the text field instead.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

++

assertSearchResponse(r);

assertThat(client().admin().indices().prepareStats("cache_test_idx").setRequestCache(true).get().getTotal().getRequestCache()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
public abstract class ConstantFieldType extends MappedFieldType {

public ConstantFieldType(String name, Map<String, String> meta) {
super(name, true, false, true, TextSearchInfo.SIMPLE_MATCH_ONLY, meta);
super(name, true, false, true, TextSearchInfo.SIMPLE_MATCH_WITHOUT_TERMS, meta);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ public static final class DateFieldType extends MappedFieldType {
public DateFieldType(String name, boolean isSearchable, boolean isStored, boolean hasDocValues,
DateFormatter dateTimeFormatter, Resolution resolution, String nullValue,
Map<String, String> meta) {
super(name, isSearchable, isStored, hasDocValues, TextSearchInfo.SIMPLE_MATCH_ONLY, meta);
super(name, isSearchable, isStored, hasDocValues, TextSearchInfo.SIMPLE_MATCH_WITHOUT_TERMS, meta);
this.dateTimeFormatter = dateTimeFormatter;
this.dateMathParser = dateTimeFormatter.toDateMathParser();
this.resolution = resolution;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ public static final class IpFieldType extends SimpleMappedFieldType {

public IpFieldType(String name, boolean indexed, boolean stored, boolean hasDocValues,
InetAddress nullValue, Map<String, String> meta) {
super(name, indexed, stored, hasDocValues, TextSearchInfo.SIMPLE_MATCH_ONLY, meta);
super(name, indexed, stored, hasDocValues, TextSearchInfo.SIMPLE_MATCH_WITHOUT_TERMS, meta);
this.nullValue = nullValue;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -406,9 +406,11 @@ public Map<String, String> meta() {
* Returns information on how any text in this field is indexed
*
* Fields that do not support any text-based queries should return
* {@link TextSearchInfo#NONE}. Some fields (eg numeric) may support
* {@link TextSearchInfo#NONE}. Some fields (eg keyword) may support
* only simple match queries, and can return
* {@link TextSearchInfo#SIMPLE_MATCH_ONLY}
* {@link TextSearchInfo#SIMPLE_MATCH_ONLY}; other fields may support
* simple match queries without using the terms index, and can return
* {@link TextSearchInfo#SIMPLE_MATCH_WITHOUT_TERMS}
*/
public TextSearchInfo getTextSearchInfo() {
return textSearchInfo;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -894,7 +894,7 @@ public static class NumberFieldType extends SimpleMappedFieldType {

public NumberFieldType(String name, NumberType type, boolean isSearchable, boolean isStored,
boolean hasDocValues, boolean coerce, Number nullValue, Map<String, String> meta) {
super(name, isSearchable, isStored, hasDocValues, TextSearchInfo.SIMPLE_MATCH_ONLY, meta);
super(name, isSearchable, isStored, hasDocValues, TextSearchInfo.SIMPLE_MATCH_WITHOUT_TERMS, meta);
this.type = Objects.requireNonNull(type);
this.coerce = coerce;
this.nullValue = nullValue;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ public static final class RangeFieldType extends MappedFieldType {

public RangeFieldType(String name, RangeType type, boolean indexed, boolean stored,
boolean hasDocValues, boolean coerce, Map<String, String> meta) {
super(name, indexed, stored, hasDocValues, TextSearchInfo.SIMPLE_MATCH_ONLY, meta);
super(name, indexed, stored, hasDocValues, TextSearchInfo.SIMPLE_MATCH_WITHOUT_TERMS, meta);
assert type != RangeType.DATE;
this.rangeType = Objects.requireNonNull(type);
dateTimeFormatter = null;
Expand All @@ -168,7 +168,7 @@ public RangeFieldType(String name, RangeType type) {

public RangeFieldType(String name, boolean indexed, boolean stored, boolean hasDocValues, DateFormatter formatter,
boolean coerce, Map<String, String> meta) {
super(name, indexed, stored, hasDocValues, TextSearchInfo.SIMPLE_MATCH_ONLY, meta);
super(name, indexed, stored, hasDocValues, TextSearchInfo.SIMPLE_MATCH_WITHOUT_TERMS, meta);
this.rangeType = RangeType.DATE;
this.dateTimeFormatter = Objects.requireNonNull(formatter);
this.dateMathParser = dateTimeFormatter.toDateMathParser();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ static final class SeqNoFieldType extends SimpleMappedFieldType {
private static final SeqNoFieldType INSTANCE = new SeqNoFieldType();

private SeqNoFieldType() {
super(NAME, true, false, true, TextSearchInfo.SIMPLE_MATCH_ONLY, Collections.emptyMap());
super(NAME, true, false, true, TextSearchInfo.SIMPLE_MATCH_WITHOUT_TERMS, Collections.emptyMap());
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,13 @@ public class TextSearchInfo {
public static final TextSearchInfo WHITESPACE_MATCH_ONLY
= new TextSearchInfo(SIMPLE_MATCH_ONLY_FIELD_TYPE, null, Lucene.WHITESPACE_ANALYZER, Lucene.WHITESPACE_ANALYZER);

/**
* Defines indexing information for fields that support simple match text queries
* without using the terms index
*/
public static final TextSearchInfo SIMPLE_MATCH_WITHOUT_TERMS
= new TextSearchInfo(SIMPLE_MATCH_ONLY_FIELD_TYPE, null, Lucene.KEYWORD_ANALYZER, Lucene.KEYWORD_ANALYZER);

private static final NamedAnalyzer FORBIDDEN_ANALYZER = new NamedAnalyzer("", AnalyzerScope.GLOBAL,
new Analyzer() {
@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ static final class VersionFieldType extends MappedFieldType {
public static final VersionFieldType INSTANCE = new VersionFieldType();

private VersionFieldType() {
super(NAME, false, false, true, TextSearchInfo.SIMPLE_MATCH_ONLY, Collections.emptyMap());
super(NAME, false, false, true, TextSearchInfo.NONE, Collections.emptyMap());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems to have slipped when I double checked all the mappers, maybe it does not have a test so we don't enforce its consistency.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, there's no test for VersionFieldMapper - I'll add one as a follow up.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thank you

}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import org.elasticsearch.common.util.BytesRefHash;
import org.elasticsearch.common.util.ObjectArray;
import org.elasticsearch.index.mapper.MappedFieldType;
import org.elasticsearch.index.mapper.TextSearchInfo;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.search.DocValueFormat;
import org.elasticsearch.search.aggregations.Aggregator;
Expand Down Expand Up @@ -84,9 +85,9 @@ public SignificantTextAggregatorFactory(String name,
// Note that if the field is unmapped (its field type is null), we don't fail,
// and just use the given field name as a placeholder.
this.fieldType = context.getFieldType(fieldName);
if (fieldType != null && fieldType.indexAnalyzer() == null) {
throw new IllegalArgumentException("Field [" + fieldType.name() + "] has no analyzer, but SignificantText " +
"requires an analyzed field");
if (fieldType != null && supportsAgg(fieldType) == false) {
throw new IllegalArgumentException("Field [" + fieldType.name() + "] of type ["
+ fieldType.typeName() + "] does not support significant text aggregations");
}
this.indexedFieldName = fieldType != null ? fieldType.name() : fieldName;
this.sourceFieldNames = sourceFieldNames == null ? new String[] { indexedFieldName } : sourceFieldNames;
Expand All @@ -98,6 +99,13 @@ public SignificantTextAggregatorFactory(String name,
this.significanceHeuristic = significanceHeuristic;
}

private static boolean supportsAgg(MappedFieldType ft) {
if (ft.getTextSearchInfo() == TextSearchInfo.NONE) {
return false;
}
return ft.getTextSearchInfo() != TextSearchInfo.SIMPLE_MATCH_WITHOUT_TERMS;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should it be return ft.getTextSearchInfo != NONE && gt.getTextSearchIngo != SIMPLE_MATCH_WITHOUT_TERMS ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

++

}

@Override
protected Aggregator createInternal(SearchContext searchContext, Aggregator parent, CardinalityUpperBound cardinality,
Map<String, Object> metadata) throws IOException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,11 +78,7 @@ protected AggregationBuilder createAggBuilderForTypeTest(MappedFieldType fieldTy

@Override
protected List<ValuesSourceType> getSupportedValuesSourceTypes() {
// TODO it is likely accidental that SigText supports anything other than Bytes, and then only text fields
return List.of(CoreValuesSourceType.NUMERIC,
CoreValuesSourceType.BYTES,
CoreValuesSourceType.RANGE,
CoreValuesSourceType.GEOPOINT);
return List.of(CoreValuesSourceType.BYTES);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ public UnsignedLongFieldType(
Number nullValueFormatted,
Map<String, String> meta
) {
super(name, indexed, isStored, hasDocValues, TextSearchInfo.SIMPLE_MATCH_ONLY, meta);
super(name, indexed, isStored, hasDocValues, TextSearchInfo.SIMPLE_MATCH_WITHOUT_TERMS, meta);
this.nullValueFormatted = nullValueFormatted;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ abstract class AbstractScriptFieldType<LeafFactory> extends MappedFieldType {
TriFunction<String, Map<String, Object>, SearchLookup, LeafFactory> factory,
Map<String, String> meta
) {
super(name, false, false, false, TextSearchInfo.SIMPLE_MATCH_ONLY, meta);
super(name, false, false, false, TextSearchInfo.SIMPLE_MATCH_WITHOUT_TERMS, meta);
this.script = script;
this.factory = factory;
}
Expand Down