Fix FuzzyQuery to properly handle Object, number, dates or String.
This makes FuzzyQueryBuilder and Parser take an Object as a value using the same logic as termQuery, so that numbers, dates or Strings would be properly handled. Relates #11865 Closes #12020
This commit is contained in:
parent
786d034d75
commit
a6c0007325
|
@ -25,14 +25,7 @@ import org.apache.lucene.index.IndexOptions;
|
||||||
import org.apache.lucene.index.Term;
|
import org.apache.lucene.index.Term;
|
||||||
import org.apache.lucene.index.Terms;
|
import org.apache.lucene.index.Terms;
|
||||||
import org.apache.lucene.queries.TermsQuery;
|
import org.apache.lucene.queries.TermsQuery;
|
||||||
import org.apache.lucene.search.ConstantScoreQuery;
|
import org.apache.lucene.search.*;
|
||||||
import org.apache.lucene.search.FuzzyQuery;
|
|
||||||
import org.apache.lucene.search.MultiTermQuery;
|
|
||||||
import org.apache.lucene.search.PrefixQuery;
|
|
||||||
import org.apache.lucene.search.Query;
|
|
||||||
import org.apache.lucene.search.RegexpQuery;
|
|
||||||
import org.apache.lucene.search.TermQuery;
|
|
||||||
import org.apache.lucene.search.TermRangeQuery;
|
|
||||||
import org.apache.lucene.util.BytesRef;
|
import org.apache.lucene.util.BytesRef;
|
||||||
import org.elasticsearch.action.fieldstats.FieldStats;
|
import org.elasticsearch.action.fieldstats.FieldStats;
|
||||||
import org.elasticsearch.common.Nullable;
|
import org.elasticsearch.common.Nullable;
|
||||||
|
@ -463,8 +456,8 @@ public abstract class MappedFieldType extends FieldType {
|
||||||
includeLower, includeUpper);
|
includeLower, includeUpper);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Query fuzzyQuery(String value, Fuzziness fuzziness, int prefixLength, int maxExpansions, boolean transpositions) {
|
public Query fuzzyQuery(Object value, Fuzziness fuzziness, int prefixLength, int maxExpansions, boolean transpositions) {
|
||||||
return new FuzzyQuery(createTerm(value), fuzziness.asDistance(value), prefixLength, maxExpansions, transpositions);
|
return new FuzzyQuery(createTerm(value), fuzziness.asDistance(BytesRefs.toString(value)), prefixLength, maxExpansions, transpositions);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Query prefixQuery(Object value, @Nullable MultiTermQuery.RewriteMethod method, @Nullable QueryParseContext context) {
|
public Query prefixQuery(Object value, @Nullable MultiTermQuery.RewriteMethod method, @Nullable QueryParseContext context) {
|
||||||
|
|
|
@ -171,8 +171,8 @@ public class ByteFieldMapper extends NumberFieldMapper {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Query fuzzyQuery(String value, Fuzziness fuzziness, int prefixLength, int maxExpansions, boolean transpositions) {
|
public Query fuzzyQuery(Object value, Fuzziness fuzziness, int prefixLength, int maxExpansions, boolean transpositions) {
|
||||||
byte iValue = Byte.parseByte(value);
|
byte iValue = parseValue(value);
|
||||||
byte iSim = fuzziness.asByte();
|
byte iSim = fuzziness.asByte();
|
||||||
return NumericRangeQuery.newIntRange(names().indexName(), numericPrecisionStep(),
|
return NumericRangeQuery.newIntRange(names().indexName(), numericPrecisionStep(),
|
||||||
iValue - iSim,
|
iValue - iSim,
|
||||||
|
|
|
@ -395,8 +395,8 @@ public class DateFieldMapper extends NumberFieldMapper {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Query fuzzyQuery(String value, Fuzziness fuzziness, int prefixLength, int maxExpansions, boolean transpositions) {
|
public Query fuzzyQuery(Object value, Fuzziness fuzziness, int prefixLength, int maxExpansions, boolean transpositions) {
|
||||||
long iValue = dateMathParser().parse(value, now());
|
long iValue = parseValue(value);
|
||||||
long iSim;
|
long iSim;
|
||||||
try {
|
try {
|
||||||
iSim = fuzziness.asTimeValue().millis();
|
iSim = fuzziness.asTimeValue().millis();
|
||||||
|
|
|
@ -20,7 +20,6 @@
|
||||||
package org.elasticsearch.index.mapper.core;
|
package org.elasticsearch.index.mapper.core;
|
||||||
|
|
||||||
import com.carrotsearch.hppc.DoubleArrayList;
|
import com.carrotsearch.hppc.DoubleArrayList;
|
||||||
|
|
||||||
import org.apache.lucene.analysis.Analyzer;
|
import org.apache.lucene.analysis.Analyzer;
|
||||||
import org.apache.lucene.analysis.TokenStream;
|
import org.apache.lucene.analysis.TokenStream;
|
||||||
import org.apache.lucene.document.Field;
|
import org.apache.lucene.document.Field;
|
||||||
|
@ -178,8 +177,8 @@ public class DoubleFieldMapper extends NumberFieldMapper {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Query fuzzyQuery(String value, Fuzziness fuzziness, int prefixLength, int maxExpansions, boolean transpositions) {
|
public Query fuzzyQuery(Object value, Fuzziness fuzziness, int prefixLength, int maxExpansions, boolean transpositions) {
|
||||||
double iValue = Double.parseDouble(value);
|
double iValue = parseDoubleValue(value);
|
||||||
double iSim = fuzziness.asDouble();
|
double iSim = fuzziness.asDouble();
|
||||||
return NumericRangeQuery.newDoubleRange(names().indexName(), numericPrecisionStep(),
|
return NumericRangeQuery.newDoubleRange(names().indexName(), numericPrecisionStep(),
|
||||||
iValue - iSim,
|
iValue - iSim,
|
||||||
|
|
|
@ -20,7 +20,6 @@
|
||||||
package org.elasticsearch.index.mapper.core;
|
package org.elasticsearch.index.mapper.core;
|
||||||
|
|
||||||
import com.carrotsearch.hppc.FloatArrayList;
|
import com.carrotsearch.hppc.FloatArrayList;
|
||||||
|
|
||||||
import org.apache.lucene.analysis.Analyzer;
|
import org.apache.lucene.analysis.Analyzer;
|
||||||
import org.apache.lucene.analysis.TokenStream;
|
import org.apache.lucene.analysis.TokenStream;
|
||||||
import org.apache.lucene.document.Field;
|
import org.apache.lucene.document.Field;
|
||||||
|
@ -179,8 +178,8 @@ public class FloatFieldMapper extends NumberFieldMapper {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Query fuzzyQuery(String value, Fuzziness fuzziness, int prefixLength, int maxExpansions, boolean transpositions) {
|
public Query fuzzyQuery(Object value, Fuzziness fuzziness, int prefixLength, int maxExpansions, boolean transpositions) {
|
||||||
float iValue = Float.parseFloat(value);
|
float iValue = parseValue(value);
|
||||||
final float iSim = fuzziness.asFloat();
|
final float iSim = fuzziness.asFloat();
|
||||||
return NumericRangeQuery.newFloatRange(names().indexName(), numericPrecisionStep(),
|
return NumericRangeQuery.newFloatRange(names().indexName(), numericPrecisionStep(),
|
||||||
iValue - iSim,
|
iValue - iSim,
|
||||||
|
|
|
@ -180,8 +180,8 @@ public class IntegerFieldMapper extends NumberFieldMapper {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Query fuzzyQuery(String value, Fuzziness fuzziness, int prefixLength, int maxExpansions, boolean transpositions) {
|
public Query fuzzyQuery(Object value, Fuzziness fuzziness, int prefixLength, int maxExpansions, boolean transpositions) {
|
||||||
int iValue = Integer.parseInt(value);
|
int iValue = parseValue(value);
|
||||||
int iSim = fuzziness.asInt();
|
int iSim = fuzziness.asInt();
|
||||||
return NumericRangeQuery.newIntRange(names().indexName(), numericPrecisionStep(),
|
return NumericRangeQuery.newIntRange(names().indexName(), numericPrecisionStep(),
|
||||||
iValue - iSim,
|
iValue - iSim,
|
||||||
|
|
|
@ -178,8 +178,8 @@ public class LongFieldMapper extends NumberFieldMapper {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Query fuzzyQuery(String value, Fuzziness fuzziness, int prefixLength, int maxExpansions, boolean transpositions) {
|
public Query fuzzyQuery(Object value, Fuzziness fuzziness, int prefixLength, int maxExpansions, boolean transpositions) {
|
||||||
long iValue = Long.parseLong(value);
|
long iValue = parseLongValue(value);
|
||||||
final long iSim = fuzziness.asLong();
|
final long iSim = fuzziness.asLong();
|
||||||
return NumericRangeQuery.newLongRange(names().indexName(), numericPrecisionStep(),
|
return NumericRangeQuery.newLongRange(names().indexName(), numericPrecisionStep(),
|
||||||
iValue - iSim,
|
iValue - iSim,
|
||||||
|
|
|
@ -20,7 +20,6 @@
|
||||||
package org.elasticsearch.index.mapper.core;
|
package org.elasticsearch.index.mapper.core;
|
||||||
|
|
||||||
import com.carrotsearch.hppc.LongArrayList;
|
import com.carrotsearch.hppc.LongArrayList;
|
||||||
|
|
||||||
import org.apache.lucene.analysis.Analyzer;
|
import org.apache.lucene.analysis.Analyzer;
|
||||||
import org.apache.lucene.analysis.NumericTokenStream;
|
import org.apache.lucene.analysis.NumericTokenStream;
|
||||||
import org.apache.lucene.analysis.TokenStream;
|
import org.apache.lucene.analysis.TokenStream;
|
||||||
|
@ -42,13 +41,7 @@ import org.elasticsearch.common.util.ByteUtils;
|
||||||
import org.elasticsearch.common.util.CollectionUtils;
|
import org.elasticsearch.common.util.CollectionUtils;
|
||||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||||
import org.elasticsearch.index.analysis.NamedAnalyzer;
|
import org.elasticsearch.index.analysis.NamedAnalyzer;
|
||||||
import org.elasticsearch.index.mapper.FieldMapper;
|
import org.elasticsearch.index.mapper.*;
|
||||||
import org.elasticsearch.index.mapper.MappedFieldType;
|
|
||||||
import org.elasticsearch.index.mapper.Mapper;
|
|
||||||
import org.elasticsearch.index.mapper.MapperParsingException;
|
|
||||||
import org.elasticsearch.index.mapper.MergeMappingException;
|
|
||||||
import org.elasticsearch.index.mapper.MergeResult;
|
|
||||||
import org.elasticsearch.index.mapper.ParseContext;
|
|
||||||
import org.elasticsearch.index.mapper.internal.AllFieldMapper;
|
import org.elasticsearch.index.mapper.internal.AllFieldMapper;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -158,7 +151,7 @@ public abstract class NumberFieldMapper extends FieldMapper implements AllFieldM
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public abstract Query fuzzyQuery(String value, Fuzziness fuzziness, int prefixLength, int maxExpansions, boolean transpositions);
|
public abstract Query fuzzyQuery(Object value, Fuzziness fuzziness, int prefixLength, int maxExpansions, boolean transpositions);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean useTermQueryWithQueryString() {
|
public boolean useTermQueryWithQueryString() {
|
||||||
|
|
|
@ -176,8 +176,8 @@ public class ShortFieldMapper extends NumberFieldMapper {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Query fuzzyQuery(String value, Fuzziness fuzziness, int prefixLength, int maxExpansions, boolean transpositions) {
|
public Query fuzzyQuery(Object value, Fuzziness fuzziness, int prefixLength, int maxExpansions, boolean transpositions) {
|
||||||
short iValue = Short.parseShort(value);
|
short iValue = parseValue(value);
|
||||||
short iSim = fuzziness.asShort();
|
short iSim = fuzziness.asShort();
|
||||||
return NumericRangeQuery.newIntRange(names().indexName(), numericPrecisionStep(),
|
return NumericRangeQuery.newIntRange(names().indexName(), numericPrecisionStep(),
|
||||||
iValue - iSim,
|
iValue - iSim,
|
||||||
|
|
|
@ -20,7 +20,6 @@
|
||||||
package org.elasticsearch.index.mapper.ip;
|
package org.elasticsearch.index.mapper.ip;
|
||||||
|
|
||||||
import com.google.common.net.InetAddresses;
|
import com.google.common.net.InetAddresses;
|
||||||
|
|
||||||
import org.apache.lucene.analysis.NumericTokenStream;
|
import org.apache.lucene.analysis.NumericTokenStream;
|
||||||
import org.apache.lucene.document.Field;
|
import org.apache.lucene.document.Field;
|
||||||
import org.apache.lucene.index.IndexOptions;
|
import org.apache.lucene.index.IndexOptions;
|
||||||
|
@ -218,8 +217,8 @@ public class IpFieldMapper extends NumberFieldMapper {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Query fuzzyQuery(String value, Fuzziness fuzziness, int prefixLength, int maxExpansions, boolean transpositions) {
|
public Query fuzzyQuery(Object value, Fuzziness fuzziness, int prefixLength, int maxExpansions, boolean transpositions) {
|
||||||
long iValue = ipToLong(value);
|
long iValue = parseValue(value);
|
||||||
long iSim;
|
long iSim;
|
||||||
try {
|
try {
|
||||||
iSim = ipToLong(fuzziness.asString());
|
iSim = ipToLong(fuzziness.asString());
|
||||||
|
|
|
@ -49,16 +49,77 @@ public class FuzzyQueryBuilder extends MultiTermQueryBuilder implements Boostabl
|
||||||
private String queryName;
|
private String queryName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new term query.
|
* Constructs a new fuzzy query.
|
||||||
*
|
*
|
||||||
* @param name The name of the field
|
* @param name The name of the field
|
||||||
* @param value The value of the term
|
* @param value The value of the text
|
||||||
*/
|
*/
|
||||||
public FuzzyQueryBuilder(String name, Object value) {
|
public FuzzyQueryBuilder(String name, Object value) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.value = value;
|
this.value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new fuzzy query.
|
||||||
|
*
|
||||||
|
* @param name The name of the field
|
||||||
|
* @param value The value of the text
|
||||||
|
*/
|
||||||
|
public FuzzyQueryBuilder(String name, String value) {
|
||||||
|
this(name, (Object) value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new fuzzy query.
|
||||||
|
*
|
||||||
|
* @param name The name of the field
|
||||||
|
* @param value The value of the text
|
||||||
|
*/
|
||||||
|
public FuzzyQueryBuilder(String name, int value) {
|
||||||
|
this(name, (Object) value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new fuzzy query.
|
||||||
|
*
|
||||||
|
* @param name The name of the field
|
||||||
|
* @param value The value of the text
|
||||||
|
*/
|
||||||
|
public FuzzyQueryBuilder(String name, long value) {
|
||||||
|
this(name, (Object) value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new fuzzy query.
|
||||||
|
*
|
||||||
|
* @param name The name of the field
|
||||||
|
* @param value The value of the text
|
||||||
|
*/
|
||||||
|
public FuzzyQueryBuilder(String name, float value) {
|
||||||
|
this(name, (Object) value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new fuzzy query.
|
||||||
|
*
|
||||||
|
* @param name The name of the field
|
||||||
|
* @param value The value of the text
|
||||||
|
*/
|
||||||
|
public FuzzyQueryBuilder(String name, double value) {
|
||||||
|
this(name, (Object) value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// NO COMMIT: not sure we should also allow boolean?
|
||||||
|
/**
|
||||||
|
* Constructs a new fuzzy query.
|
||||||
|
*
|
||||||
|
* @param name The name of the field
|
||||||
|
* @param value The value of the text
|
||||||
|
*/
|
||||||
|
public FuzzyQueryBuilder(String name, boolean value) {
|
||||||
|
this(name, (Object) value);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the boost for this query. Documents matching this query will (in addition to the normal
|
* Sets the boost for this query. Documents matching this query will (in addition to the normal
|
||||||
* weightings) have their score multiplied by the boost provided.
|
* weightings) have their score multiplied by the boost provided.
|
||||||
|
|
|
@ -25,6 +25,7 @@ import org.apache.lucene.search.MultiTermQuery;
|
||||||
import org.apache.lucene.search.Query;
|
import org.apache.lucene.search.Query;
|
||||||
import org.elasticsearch.common.ParseField;
|
import org.elasticsearch.common.ParseField;
|
||||||
import org.elasticsearch.common.inject.Inject;
|
import org.elasticsearch.common.inject.Inject;
|
||||||
|
import org.elasticsearch.common.lucene.BytesRefs;
|
||||||
import org.elasticsearch.common.unit.Fuzziness;
|
import org.elasticsearch.common.unit.Fuzziness;
|
||||||
import org.elasticsearch.common.xcontent.XContentParser;
|
import org.elasticsearch.common.xcontent.XContentParser;
|
||||||
import org.elasticsearch.index.mapper.MappedFieldType;
|
import org.elasticsearch.index.mapper.MappedFieldType;
|
||||||
|
@ -61,7 +62,7 @@ public class FuzzyQueryParser implements QueryParser {
|
||||||
}
|
}
|
||||||
String fieldName = parser.currentName();
|
String fieldName = parser.currentName();
|
||||||
|
|
||||||
String value = null;
|
Object value = null;
|
||||||
float boost = 1.0f;
|
float boost = 1.0f;
|
||||||
Fuzziness fuzziness = DEFAULT_FUZZINESS;
|
Fuzziness fuzziness = DEFAULT_FUZZINESS;
|
||||||
int prefixLength = FuzzyQuery.defaultPrefixLength;
|
int prefixLength = FuzzyQuery.defaultPrefixLength;
|
||||||
|
@ -80,9 +81,9 @@ public class FuzzyQueryParser implements QueryParser {
|
||||||
currentFieldName = parser.currentName();
|
currentFieldName = parser.currentName();
|
||||||
} else {
|
} else {
|
||||||
if ("term".equals(currentFieldName)) {
|
if ("term".equals(currentFieldName)) {
|
||||||
value = parser.text();
|
value = parser.objectBytes();
|
||||||
} else if ("value".equals(currentFieldName)) {
|
} else if ("value".equals(currentFieldName)) {
|
||||||
value = parser.text();
|
value = parser.objectBytes();
|
||||||
} else if ("boost".equals(currentFieldName)) {
|
} else if ("boost".equals(currentFieldName)) {
|
||||||
boost = parser.floatValue();
|
boost = parser.floatValue();
|
||||||
} else if (parseContext.parseFieldMatcher().match(currentFieldName, FUZZINESS)) {
|
} else if (parseContext.parseFieldMatcher().match(currentFieldName, FUZZINESS)) {
|
||||||
|
@ -104,7 +105,7 @@ public class FuzzyQueryParser implements QueryParser {
|
||||||
}
|
}
|
||||||
parser.nextToken();
|
parser.nextToken();
|
||||||
} else {
|
} else {
|
||||||
value = parser.text();
|
value = parser.objectBytes();
|
||||||
// move to the next token
|
// move to the next token
|
||||||
parser.nextToken();
|
parser.nextToken();
|
||||||
}
|
}
|
||||||
|
@ -112,14 +113,15 @@ public class FuzzyQueryParser implements QueryParser {
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
throw new QueryParsingException(parseContext, "No value specified for fuzzy query");
|
throw new QueryParsingException(parseContext, "No value specified for fuzzy query");
|
||||||
}
|
}
|
||||||
|
|
||||||
Query query = null;
|
Query query = null;
|
||||||
MappedFieldType fieldType = parseContext.fieldMapper(fieldName);
|
MappedFieldType fieldType = parseContext.fieldMapper(fieldName);
|
||||||
if (fieldType != null) {
|
if (fieldType != null) {
|
||||||
query = fieldType.fuzzyQuery(value, fuzziness, prefixLength, maxExpansions, transpositions);
|
query = fieldType.fuzzyQuery(value, fuzziness, prefixLength, maxExpansions, transpositions);
|
||||||
}
|
}
|
||||||
if (query == null) {
|
if (query == null) {
|
||||||
query = new FuzzyQuery(new Term(fieldName, value), fuzziness.asDistance(value), prefixLength, maxExpansions, transpositions);
|
int maxEdits = fuzziness.asDistance(BytesRefs.toString(value));
|
||||||
|
query = new FuzzyQuery(new Term(fieldName, BytesRefs.toBytesRef(value)), maxEdits, prefixLength, maxExpansions, transpositions);
|
||||||
}
|
}
|
||||||
if (query instanceof MultiTermQuery) {
|
if (query instanceof MultiTermQuery) {
|
||||||
QueryParsers.setRewriteMethod((MultiTermQuery) query, rewriteMethod);
|
QueryParsers.setRewriteMethod((MultiTermQuery) query, rewriteMethod);
|
||||||
|
|
Loading…
Reference in New Issue