|
@@ -31,8 +31,10 @@ import org.apache.lucene.util.automaton.CompiledAutomaton.AUTOMATON_TYPE;
|
|
|
import org.apache.lucene.util.automaton.MinimizationOperations;
|
|
|
import org.apache.lucene.util.automaton.Operations;
|
|
|
import org.elasticsearch.common.bytes.BytesReference;
|
|
|
+import org.elasticsearch.common.lucene.BytesRefs;
|
|
|
import org.elasticsearch.common.lucene.Lucene;
|
|
|
import org.elasticsearch.common.lucene.search.AutomatonQueries;
|
|
|
+import org.elasticsearch.common.unit.Fuzziness;
|
|
|
import org.elasticsearch.index.analysis.IndexAnalyzers;
|
|
|
import org.elasticsearch.index.analysis.NamedAnalyzer;
|
|
|
import org.elasticsearch.index.fielddata.FieldData;
|
|
@@ -44,9 +46,15 @@ import org.elasticsearch.script.Script;
|
|
|
import org.elasticsearch.script.ScriptCompiler;
|
|
|
import org.elasticsearch.script.StringFieldScript;
|
|
|
import org.elasticsearch.script.field.KeywordDocValuesField;
|
|
|
+import org.elasticsearch.script.field.SortedSetDocValuesStringFieldScript;
|
|
|
import org.elasticsearch.search.aggregations.support.CoreValuesSourceType;
|
|
|
import org.elasticsearch.search.lookup.FieldValues;
|
|
|
import org.elasticsearch.search.lookup.SearchLookup;
|
|
|
+import org.elasticsearch.search.runtime.StringScriptFieldFuzzyQuery;
|
|
|
+import org.elasticsearch.search.runtime.StringScriptFieldPrefixQuery;
|
|
|
+import org.elasticsearch.search.runtime.StringScriptFieldRegexpQuery;
|
|
|
+import org.elasticsearch.search.runtime.StringScriptFieldTermQuery;
|
|
|
+import org.elasticsearch.search.runtime.StringScriptFieldWildcardQuery;
|
|
|
import org.elasticsearch.xcontent.XContentParser;
|
|
|
|
|
|
import java.io.IOException;
|
|
@@ -388,6 +396,68 @@ public final class KeywordFieldMapper extends FieldMapper {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ @Override
|
|
|
+ public Query fuzzyQuery(
|
|
|
+ Object value,
|
|
|
+ Fuzziness fuzziness,
|
|
|
+ int prefixLength,
|
|
|
+ int maxExpansions,
|
|
|
+ boolean transpositions,
|
|
|
+ SearchExecutionContext context
|
|
|
+ ) {
|
|
|
+ failIfNotIndexedNorDocValuesFallback(context);
|
|
|
+ if (isIndexed()) {
|
|
|
+ return super.fuzzyQuery(value, fuzziness, prefixLength, maxExpansions, transpositions, context);
|
|
|
+ } else {
|
|
|
+ return StringScriptFieldFuzzyQuery.build(
|
|
|
+ new Script(""),
|
|
|
+ ctx -> new SortedSetDocValuesStringFieldScript(name(), context.lookup(), ctx),
|
|
|
+ name(),
|
|
|
+ indexedValueForSearch(value).utf8ToString(),
|
|
|
+ fuzziness.asDistance(BytesRefs.toString(value)),
|
|
|
+ prefixLength,
|
|
|
+ transpositions
|
|
|
+ );
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Query prefixQuery(
|
|
|
+ String value,
|
|
|
+ MultiTermQuery.RewriteMethod method,
|
|
|
+ boolean caseInsensitive,
|
|
|
+ SearchExecutionContext context
|
|
|
+ ) {
|
|
|
+ failIfNotIndexedNorDocValuesFallback(context);
|
|
|
+ if (isIndexed()) {
|
|
|
+ return super.prefixQuery(value, method, caseInsensitive, context);
|
|
|
+ } else {
|
|
|
+ return new StringScriptFieldPrefixQuery(
|
|
|
+ new Script(""),
|
|
|
+ ctx -> new SortedSetDocValuesStringFieldScript(name(), context.lookup(), ctx),
|
|
|
+ name(),
|
|
|
+ indexedValueForSearch(value).utf8ToString(),
|
|
|
+ caseInsensitive
|
|
|
+ );
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Query termQueryCaseInsensitive(Object value, SearchExecutionContext context) {
|
|
|
+ failIfNotIndexedNorDocValuesFallback(context);
|
|
|
+ if (isIndexed()) {
|
|
|
+ return super.termQueryCaseInsensitive(value, context);
|
|
|
+ } else {
|
|
|
+ return new StringScriptFieldTermQuery(
|
|
|
+ new Script(""),
|
|
|
+ ctx -> new SortedSetDocValuesStringFieldScript(name(), context.lookup(), ctx),
|
|
|
+ name(),
|
|
|
+ indexedValueForSearch(value).utf8ToString(),
|
|
|
+ true
|
|
|
+ );
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
@Override
|
|
|
public TermsEnum getTerms(boolean caseInsensitive, String string, SearchExecutionContext queryShardContext, String searchAfter)
|
|
|
throws IOException {
|
|
@@ -521,7 +591,72 @@ public final class KeywordFieldMapper extends FieldMapper {
|
|
|
boolean caseInsensitive,
|
|
|
SearchExecutionContext context
|
|
|
) {
|
|
|
- return super.wildcardQuery(value, method, caseInsensitive, true, context);
|
|
|
+ failIfNotIndexedNorDocValuesFallback(context);
|
|
|
+ if (isIndexed()) {
|
|
|
+ return super.wildcardQuery(value, method, caseInsensitive, true, context);
|
|
|
+ } else {
|
|
|
+ if (getTextSearchInfo().getSearchAnalyzer() != null) {
|
|
|
+ value = normalizeWildcardPattern(name(), value, getTextSearchInfo().getSearchAnalyzer());
|
|
|
+ } else {
|
|
|
+ value = indexedValueForSearch(value).utf8ToString();
|
|
|
+ }
|
|
|
+ return new StringScriptFieldWildcardQuery(
|
|
|
+ new Script(""),
|
|
|
+ ctx -> new SortedSetDocValuesStringFieldScript(name(), context.lookup(), ctx),
|
|
|
+ name(),
|
|
|
+ value,
|
|
|
+ caseInsensitive
|
|
|
+ );
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Query normalizedWildcardQuery(String value, MultiTermQuery.RewriteMethod method, SearchExecutionContext context) {
|
|
|
+ failIfNotIndexedNorDocValuesFallback(context);
|
|
|
+ if (isIndexed()) {
|
|
|
+ return super.normalizedWildcardQuery(value, method, context);
|
|
|
+ } else {
|
|
|
+ if (getTextSearchInfo().getSearchAnalyzer() != null) {
|
|
|
+ value = normalizeWildcardPattern(name(), value, getTextSearchInfo().getSearchAnalyzer());
|
|
|
+ } else {
|
|
|
+ value = indexedValueForSearch(value).utf8ToString();
|
|
|
+ }
|
|
|
+ return new StringScriptFieldWildcardQuery(
|
|
|
+ new Script(""),
|
|
|
+ ctx -> new SortedSetDocValuesStringFieldScript(name(), context.lookup(), ctx),
|
|
|
+ name(),
|
|
|
+ value,
|
|
|
+ false
|
|
|
+ );
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Query regexpQuery(
|
|
|
+ String value,
|
|
|
+ int syntaxFlags,
|
|
|
+ int matchFlags,
|
|
|
+ int maxDeterminizedStates,
|
|
|
+ MultiTermQuery.RewriteMethod method,
|
|
|
+ SearchExecutionContext context
|
|
|
+ ) {
|
|
|
+ failIfNotIndexedNorDocValuesFallback(context);
|
|
|
+ if (isIndexed()) {
|
|
|
+ return super.regexpQuery(value, syntaxFlags, matchFlags, maxDeterminizedStates, method, context);
|
|
|
+ } else {
|
|
|
+ if (matchFlags != 0) {
|
|
|
+ throw new IllegalArgumentException("Match flags not yet implemented [" + matchFlags + "]");
|
|
|
+ }
|
|
|
+ return new StringScriptFieldRegexpQuery(
|
|
|
+ new Script(""),
|
|
|
+ ctx -> new SortedSetDocValuesStringFieldScript(name(), context.lookup(), ctx),
|
|
|
+ name(),
|
|
|
+ indexedValueForSearch(value).utf8ToString(),
|
|
|
+ syntaxFlags,
|
|
|
+ matchFlags,
|
|
|
+ maxDeterminizedStates
|
|
|
+ );
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
@Override
|