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:
Alex Ksikes 2015-07-02 19:43:48 -05:00
parent 786d034d75
commit a6c0007325
12 changed files with 92 additions and 46 deletions

View File

@ -25,14 +25,7 @@ import org.apache.lucene.index.IndexOptions;
import org.apache.lucene.index.Term;
import org.apache.lucene.index.Terms;
import org.apache.lucene.queries.TermsQuery;
import org.apache.lucene.search.ConstantScoreQuery;
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.search.*;
import org.apache.lucene.util.BytesRef;
import org.elasticsearch.action.fieldstats.FieldStats;
import org.elasticsearch.common.Nullable;
@ -463,8 +456,8 @@ public abstract class MappedFieldType extends FieldType {
includeLower, includeUpper);
}
public Query fuzzyQuery(String value, Fuzziness fuzziness, int prefixLength, int maxExpansions, boolean transpositions) {
return new FuzzyQuery(createTerm(value), fuzziness.asDistance(value), prefixLength, maxExpansions, transpositions);
public Query fuzzyQuery(Object value, Fuzziness fuzziness, int prefixLength, int maxExpansions, boolean 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) {

View File

@ -171,8 +171,8 @@ public class ByteFieldMapper extends NumberFieldMapper {
}
@Override
public Query fuzzyQuery(String value, Fuzziness fuzziness, int prefixLength, int maxExpansions, boolean transpositions) {
byte iValue = Byte.parseByte(value);
public Query fuzzyQuery(Object value, Fuzziness fuzziness, int prefixLength, int maxExpansions, boolean transpositions) {
byte iValue = parseValue(value);
byte iSim = fuzziness.asByte();
return NumericRangeQuery.newIntRange(names().indexName(), numericPrecisionStep(),
iValue - iSim,

View File

@ -395,8 +395,8 @@ public class DateFieldMapper extends NumberFieldMapper {
}
@Override
public Query fuzzyQuery(String value, Fuzziness fuzziness, int prefixLength, int maxExpansions, boolean transpositions) {
long iValue = dateMathParser().parse(value, now());
public Query fuzzyQuery(Object value, Fuzziness fuzziness, int prefixLength, int maxExpansions, boolean transpositions) {
long iValue = parseValue(value);
long iSim;
try {
iSim = fuzziness.asTimeValue().millis();

View File

@ -20,7 +20,6 @@
package org.elasticsearch.index.mapper.core;
import com.carrotsearch.hppc.DoubleArrayList;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.document.Field;
@ -178,8 +177,8 @@ public class DoubleFieldMapper extends NumberFieldMapper {
}
@Override
public Query fuzzyQuery(String value, Fuzziness fuzziness, int prefixLength, int maxExpansions, boolean transpositions) {
double iValue = Double.parseDouble(value);
public Query fuzzyQuery(Object value, Fuzziness fuzziness, int prefixLength, int maxExpansions, boolean transpositions) {
double iValue = parseDoubleValue(value);
double iSim = fuzziness.asDouble();
return NumericRangeQuery.newDoubleRange(names().indexName(), numericPrecisionStep(),
iValue - iSim,

View File

@ -20,7 +20,6 @@
package org.elasticsearch.index.mapper.core;
import com.carrotsearch.hppc.FloatArrayList;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.document.Field;
@ -179,8 +178,8 @@ public class FloatFieldMapper extends NumberFieldMapper {
}
@Override
public Query fuzzyQuery(String value, Fuzziness fuzziness, int prefixLength, int maxExpansions, boolean transpositions) {
float iValue = Float.parseFloat(value);
public Query fuzzyQuery(Object value, Fuzziness fuzziness, int prefixLength, int maxExpansions, boolean transpositions) {
float iValue = parseValue(value);
final float iSim = fuzziness.asFloat();
return NumericRangeQuery.newFloatRange(names().indexName(), numericPrecisionStep(),
iValue - iSim,

View File

@ -180,8 +180,8 @@ public class IntegerFieldMapper extends NumberFieldMapper {
}
@Override
public Query fuzzyQuery(String value, Fuzziness fuzziness, int prefixLength, int maxExpansions, boolean transpositions) {
int iValue = Integer.parseInt(value);
public Query fuzzyQuery(Object value, Fuzziness fuzziness, int prefixLength, int maxExpansions, boolean transpositions) {
int iValue = parseValue(value);
int iSim = fuzziness.asInt();
return NumericRangeQuery.newIntRange(names().indexName(), numericPrecisionStep(),
iValue - iSim,

View File

@ -178,8 +178,8 @@ public class LongFieldMapper extends NumberFieldMapper {
}
@Override
public Query fuzzyQuery(String value, Fuzziness fuzziness, int prefixLength, int maxExpansions, boolean transpositions) {
long iValue = Long.parseLong(value);
public Query fuzzyQuery(Object value, Fuzziness fuzziness, int prefixLength, int maxExpansions, boolean transpositions) {
long iValue = parseLongValue(value);
final long iSim = fuzziness.asLong();
return NumericRangeQuery.newLongRange(names().indexName(), numericPrecisionStep(),
iValue - iSim,

View File

@ -20,7 +20,6 @@
package org.elasticsearch.index.mapper.core;
import com.carrotsearch.hppc.LongArrayList;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.NumericTokenStream;
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.xcontent.XContentBuilder;
import org.elasticsearch.index.analysis.NamedAnalyzer;
import org.elasticsearch.index.mapper.FieldMapper;
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.*;
import org.elasticsearch.index.mapper.internal.AllFieldMapper;
import java.io.IOException;
@ -158,7 +151,7 @@ public abstract class NumberFieldMapper extends FieldMapper implements AllFieldM
}
@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
public boolean useTermQueryWithQueryString() {

View File

@ -176,8 +176,8 @@ public class ShortFieldMapper extends NumberFieldMapper {
}
@Override
public Query fuzzyQuery(String value, Fuzziness fuzziness, int prefixLength, int maxExpansions, boolean transpositions) {
short iValue = Short.parseShort(value);
public Query fuzzyQuery(Object value, Fuzziness fuzziness, int prefixLength, int maxExpansions, boolean transpositions) {
short iValue = parseValue(value);
short iSim = fuzziness.asShort();
return NumericRangeQuery.newIntRange(names().indexName(), numericPrecisionStep(),
iValue - iSim,

View File

@ -20,7 +20,6 @@
package org.elasticsearch.index.mapper.ip;
import com.google.common.net.InetAddresses;
import org.apache.lucene.analysis.NumericTokenStream;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.IndexOptions;
@ -218,8 +217,8 @@ public class IpFieldMapper extends NumberFieldMapper {
}
@Override
public Query fuzzyQuery(String value, Fuzziness fuzziness, int prefixLength, int maxExpansions, boolean transpositions) {
long iValue = ipToLong(value);
public Query fuzzyQuery(Object value, Fuzziness fuzziness, int prefixLength, int maxExpansions, boolean transpositions) {
long iValue = parseValue(value);
long iSim;
try {
iSim = ipToLong(fuzziness.asString());

View File

@ -49,16 +49,77 @@ public class FuzzyQueryBuilder extends MultiTermQueryBuilder implements Boostabl
private String queryName;
/**
* Constructs a new term query.
* Constructs a new fuzzy query.
*
* @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) {
this.name = name;
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
* weightings) have their score multiplied by the boost provided.

View File

@ -25,6 +25,7 @@ import org.apache.lucene.search.MultiTermQuery;
import org.apache.lucene.search.Query;
import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.lucene.BytesRefs;
import org.elasticsearch.common.unit.Fuzziness;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.index.mapper.MappedFieldType;
@ -61,7 +62,7 @@ public class FuzzyQueryParser implements QueryParser {
}
String fieldName = parser.currentName();
String value = null;
Object value = null;
float boost = 1.0f;
Fuzziness fuzziness = DEFAULT_FUZZINESS;
int prefixLength = FuzzyQuery.defaultPrefixLength;
@ -80,9 +81,9 @@ public class FuzzyQueryParser implements QueryParser {
currentFieldName = parser.currentName();
} else {
if ("term".equals(currentFieldName)) {
value = parser.text();
value = parser.objectBytes();
} else if ("value".equals(currentFieldName)) {
value = parser.text();
value = parser.objectBytes();
} else if ("boost".equals(currentFieldName)) {
boost = parser.floatValue();
} else if (parseContext.parseFieldMatcher().match(currentFieldName, FUZZINESS)) {
@ -104,7 +105,7 @@ public class FuzzyQueryParser implements QueryParser {
}
parser.nextToken();
} else {
value = parser.text();
value = parser.objectBytes();
// move to the next token
parser.nextToken();
}
@ -112,14 +113,15 @@ public class FuzzyQueryParser implements QueryParser {
if (value == null) {
throw new QueryParsingException(parseContext, "No value specified for fuzzy query");
}
Query query = null;
MappedFieldType fieldType = parseContext.fieldMapper(fieldName);
if (fieldType != null) {
query = fieldType.fuzzyQuery(value, fuzziness, prefixLength, maxExpansions, transpositions);
}
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) {
QueryParsers.setRewriteMethod((MultiTermQuery) query, rewriteMethod);