diff --git a/src/main/java/org/elasticsearch/action/mlt/TransportMoreLikeThisAction.java b/src/main/java/org/elasticsearch/action/mlt/TransportMoreLikeThisAction.java
index c0a36f5702f..808c6077364 100644
--- a/src/main/java/org/elasticsearch/action/mlt/TransportMoreLikeThisAction.java
+++ b/src/main/java/org/elasticsearch/action/mlt/TransportMoreLikeThisAction.java
@@ -160,7 +160,7 @@ public class TransportMoreLikeThisAction extends TransportActionAlthough most analyzers generate character terms (CharTermAttribute),
+ * some token only contain binary terms (BinaryTermAttribute,
+ * CharTermAttribute being a special type of BinaryTermAttribute), such as
+ * {@link NumericTokenStream} and unsuitable for highlighting and
+ * more-like-this queries which expect character terms.
+ */
+ public static boolean isCharacterTokenStream(TokenStream tokenStream) {
+ try {
+ tokenStream.addAttribute(CharTermAttribute.class);
+ return true;
+ } catch (IllegalArgumentException e) {
+ return false;
+ }
+ }
+
+ /**
+ * Check whether {@link TokenStream}s generated with analyzer
+ * provide with character terms.
+ * @see #isCharacterTokenStream(TokenStream)
+ */
+ public static boolean generatesCharacterTokenStream(Analyzer analyzer, String fieldName) throws IOException {
+ return isCharacterTokenStream(analyzer.tokenStream(fieldName, new StringReader("")));
+ }
+
}
diff --git a/src/main/java/org/elasticsearch/index/mapper/core/ByteFieldMapper.java b/src/main/java/org/elasticsearch/index/mapper/core/ByteFieldMapper.java
index a1a45140baf..5cce2cc8c88 100644
--- a/src/main/java/org/elasticsearch/index/mapper/core/ByteFieldMapper.java
+++ b/src/main/java/org/elasticsearch/index/mapper/core/ByteFieldMapper.java
@@ -356,7 +356,7 @@ public class ByteFieldMapper extends NumberFieldMapper {
private final NumberFieldMapper mapper;
public CustomByteNumericField(NumberFieldMapper mapper, byte number, FieldType fieldType) {
- super(mapper, mapper.fieldType.stored() ? number : null, fieldType);
+ super(mapper, number, fieldType);
this.mapper = mapper;
this.number = number;
}
diff --git a/src/main/java/org/elasticsearch/index/mapper/core/DoubleFieldMapper.java b/src/main/java/org/elasticsearch/index/mapper/core/DoubleFieldMapper.java
index 8d88cc73bd8..988ab328a16 100644
--- a/src/main/java/org/elasticsearch/index/mapper/core/DoubleFieldMapper.java
+++ b/src/main/java/org/elasticsearch/index/mapper/core/DoubleFieldMapper.java
@@ -354,7 +354,7 @@ public class DoubleFieldMapper extends NumberFieldMapper {
private final NumberFieldMapper mapper;
public CustomDoubleNumericField(NumberFieldMapper mapper, double number, FieldType fieldType) {
- super(mapper, mapper.fieldType().stored() ? number : null, fieldType);
+ super(mapper, number, fieldType);
this.mapper = mapper;
this.number = number;
}
diff --git a/src/main/java/org/elasticsearch/index/mapper/core/FloatFieldMapper.java b/src/main/java/org/elasticsearch/index/mapper/core/FloatFieldMapper.java
index 04eaf10740d..a8372b567c2 100644
--- a/src/main/java/org/elasticsearch/index/mapper/core/FloatFieldMapper.java
+++ b/src/main/java/org/elasticsearch/index/mapper/core/FloatFieldMapper.java
@@ -350,7 +350,7 @@ public class FloatFieldMapper extends NumberFieldMapper {
private final NumberFieldMapper mapper;
public CustomFloatNumericField(NumberFieldMapper mapper, float number, FieldType fieldType) {
- super(mapper, mapper.fieldType().stored() ? number : null, fieldType);
+ super(mapper, number, fieldType);
this.mapper = mapper;
this.number = number;
}
diff --git a/src/main/java/org/elasticsearch/index/mapper/core/IntegerFieldMapper.java b/src/main/java/org/elasticsearch/index/mapper/core/IntegerFieldMapper.java
index a673e6e04d7..6c0b7327bb9 100644
--- a/src/main/java/org/elasticsearch/index/mapper/core/IntegerFieldMapper.java
+++ b/src/main/java/org/elasticsearch/index/mapper/core/IntegerFieldMapper.java
@@ -353,7 +353,7 @@ public class IntegerFieldMapper extends NumberFieldMapper {
private final NumberFieldMapper mapper;
public CustomIntegerNumericField(NumberFieldMapper mapper, int number, FieldType fieldType) {
- super(mapper, mapper.fieldType().stored() ? number : null, fieldType);
+ super(mapper, number, fieldType);
this.mapper = mapper;
this.number = number;
}
diff --git a/src/main/java/org/elasticsearch/index/mapper/core/LongFieldMapper.java b/src/main/java/org/elasticsearch/index/mapper/core/LongFieldMapper.java
index 9a7e1841a43..f90955335d4 100644
--- a/src/main/java/org/elasticsearch/index/mapper/core/LongFieldMapper.java
+++ b/src/main/java/org/elasticsearch/index/mapper/core/LongFieldMapper.java
@@ -353,7 +353,7 @@ public class LongFieldMapper extends NumberFieldMapper {
private final NumberFieldMapper mapper;
public CustomLongNumericField(NumberFieldMapper mapper, long number, FieldType fieldType) {
- super(mapper, mapper.fieldType.stored() ? number : null, fieldType);
+ super(mapper, number, fieldType);
this.mapper = mapper;
this.number = number;
}
diff --git a/src/main/java/org/elasticsearch/index/mapper/core/ShortFieldMapper.java b/src/main/java/org/elasticsearch/index/mapper/core/ShortFieldMapper.java
index c1fc88be058..b4d9f7a613a 100644
--- a/src/main/java/org/elasticsearch/index/mapper/core/ShortFieldMapper.java
+++ b/src/main/java/org/elasticsearch/index/mapper/core/ShortFieldMapper.java
@@ -358,7 +358,7 @@ public class ShortFieldMapper extends NumberFieldMapper {
private final NumberFieldMapper mapper;
public CustomShortNumericField(NumberFieldMapper mapper, short number, FieldType fieldType) {
- super(mapper, mapper.fieldType().stored() ? number : null, fieldType);
+ super(mapper, number, fieldType);
this.mapper = mapper;
this.number = number;
}
diff --git a/src/main/java/org/elasticsearch/index/query/FuzzyLikeThisFieldQueryBuilder.java b/src/main/java/org/elasticsearch/index/query/FuzzyLikeThisFieldQueryBuilder.java
index 12a3c27662e..66f3badbea5 100644
--- a/src/main/java/org/elasticsearch/index/query/FuzzyLikeThisFieldQueryBuilder.java
+++ b/src/main/java/org/elasticsearch/index/query/FuzzyLikeThisFieldQueryBuilder.java
@@ -38,6 +38,7 @@ public class FuzzyLikeThisFieldQueryBuilder extends BaseQueryBuilder implements
private Integer maxQueryTerms;
private Boolean ignoreTF;
private String analyzer;
+ private boolean failOnUnsupportedField;
/**
* A fuzzy more like this query on the provided field.
@@ -89,6 +90,14 @@ public class FuzzyLikeThisFieldQueryBuilder extends BaseQueryBuilder implements
return this;
}
+ /**
+ * Whether to fail or return no result when this query is run against a field which is not supported such as binary/numeric fields.
+ */
+ public FuzzyLikeThisFieldQueryBuilder failOnUnsupportedField(boolean fail) {
+ failOnUnsupportedField = fail;
+ return this;
+ }
+
@Override
protected void doXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject(FuzzyLikeThisFieldQueryParser.NAME);
@@ -115,6 +124,9 @@ public class FuzzyLikeThisFieldQueryBuilder extends BaseQueryBuilder implements
if (analyzer != null) {
builder.field("analyzer", analyzer);
}
+ if (!failOnUnsupportedField) {
+ builder.field("fail_on_unsupported_field", failOnUnsupportedField);
+ }
builder.endObject();
builder.endObject();
}
diff --git a/src/main/java/org/elasticsearch/index/query/FuzzyLikeThisFieldQueryParser.java b/src/main/java/org/elasticsearch/index/query/FuzzyLikeThisFieldQueryParser.java
index 34b977303a4..77ce20de294 100644
--- a/src/main/java/org/elasticsearch/index/query/FuzzyLikeThisFieldQueryParser.java
+++ b/src/main/java/org/elasticsearch/index/query/FuzzyLikeThisFieldQueryParser.java
@@ -22,9 +22,11 @@ package org.elasticsearch.index.query;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.sandbox.queries.FuzzyLikeThisQuery;
import org.apache.lucene.search.Query;
+import org.elasticsearch.ElasticSearchIllegalArgumentException;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.xcontent.XContentParser;
+import org.elasticsearch.index.analysis.Analysis;
import org.elasticsearch.index.mapper.MapperService;
import java.io.IOException;
@@ -67,6 +69,7 @@ public class FuzzyLikeThisFieldQueryParser implements QueryParser {
int prefixLength = 0;
boolean ignoreTF = false;
Analyzer analyzer = null;
+ boolean failOnUnsupportedField = true;
XContentParser.Token token = parser.nextToken();
if (token != XContentParser.Token.FIELD_NAME) {
@@ -100,6 +103,8 @@ public class FuzzyLikeThisFieldQueryParser implements QueryParser {
prefixLength = parser.intValue();
} else if ("analyzer".equals(currentFieldName)) {
analyzer = parseContext.analysisService().analyzer(parser.text());
+ } else if ("fail_on_unsupported_field".equals(currentFieldName) || "failOnUnsupportedField".equals(currentFieldName)) {
+ failOnUnsupportedField = parser.booleanValue();
} else {
throw new QueryParsingException(parseContext.index(), "[flt_field] query does not support [" + currentFieldName + "]");
}
@@ -122,6 +127,13 @@ public class FuzzyLikeThisFieldQueryParser implements QueryParser {
if (analyzer == null) {
analyzer = parseContext.mapperService().searchAnalyzer();
}
+ if (!Analysis.generatesCharacterTokenStream(analyzer, fieldName)) {
+ if (failOnUnsupportedField) {
+ throw new ElasticSearchIllegalArgumentException("fuzzy_like_this_field doesn't support binary/numeric fields: [" + fieldName + "]");
+ } else {
+ return null;
+ }
+ }
FuzzyLikeThisQuery query = new FuzzyLikeThisQuery(maxNumTerms, analyzer);
query.addTerms(likeText, fieldName, minSimilarity, prefixLength);
diff --git a/src/main/java/org/elasticsearch/index/query/FuzzyLikeThisQueryBuilder.java b/src/main/java/org/elasticsearch/index/query/FuzzyLikeThisQueryBuilder.java
index df95b235172..44856254194 100644
--- a/src/main/java/org/elasticsearch/index/query/FuzzyLikeThisQueryBuilder.java
+++ b/src/main/java/org/elasticsearch/index/query/FuzzyLikeThisQueryBuilder.java
@@ -38,6 +38,7 @@ public class FuzzyLikeThisQueryBuilder extends BaseQueryBuilder implements Boost
private Integer maxQueryTerms;
private Boolean ignoreTF;
private String analyzer;
+ private boolean failOnUnsupportedField = true;;
/**
* Constructs a new fuzzy like this query which uses the "_all" field.
@@ -96,6 +97,14 @@ public class FuzzyLikeThisQueryBuilder extends BaseQueryBuilder implements Boost
return this;
}
+ /**
+ * Whether to fail or return no result when this query is run against a field which is not supported such as binary/numeric fields.
+ */
+ public FuzzyLikeThisQueryBuilder failOnUnsupportedField(boolean fail) {
+ failOnUnsupportedField = fail;
+ return this;
+ }
+
@Override
protected void doXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject(FuzzyLikeThisQueryParser.NAME);
@@ -128,6 +137,9 @@ public class FuzzyLikeThisQueryBuilder extends BaseQueryBuilder implements Boost
if (analyzer != null) {
builder.field("analyzer", analyzer);
}
+ if (!failOnUnsupportedField) {
+ builder.field("fail_on_unsupported_field", failOnUnsupportedField);
+ }
builder.endObject();
}
}
\ No newline at end of file
diff --git a/src/main/java/org/elasticsearch/index/query/FuzzyLikeThisQueryParser.java b/src/main/java/org/elasticsearch/index/query/FuzzyLikeThisQueryParser.java
index 0a1f9c02421..79f15bafdf8 100644
--- a/src/main/java/org/elasticsearch/index/query/FuzzyLikeThisQueryParser.java
+++ b/src/main/java/org/elasticsearch/index/query/FuzzyLikeThisQueryParser.java
@@ -19,14 +19,18 @@
package org.elasticsearch.index.query;
+import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.sandbox.queries.FuzzyLikeThisQuery;
import org.apache.lucene.search.Query;
+import org.elasticsearch.ElasticSearchIllegalArgumentException;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.xcontent.XContentParser;
+import org.elasticsearch.index.analysis.Analysis;
import java.io.IOException;
+import java.util.Iterator;
import java.util.List;
/**
@@ -66,6 +70,7 @@ public class FuzzyLikeThisQueryParser implements QueryParser {
int prefixLength = 0;
boolean ignoreTF = false;
Analyzer analyzer = null;
+ boolean failOnUnsupportedField = true;
XContentParser.Token token;
String currentFieldName = null;
@@ -87,12 +92,14 @@ public class FuzzyLikeThisQueryParser implements QueryParser {
prefixLength = parser.intValue();
} else if ("analyzer".equals(currentFieldName)) {
analyzer = parseContext.analysisService().analyzer(parser.text());
+ } else if ("fail_on_unsupported_field".equals(currentFieldName) || "failOnUnsupportedField".equals(currentFieldName)) {
+ failOnUnsupportedField = parser.booleanValue();
} else {
throw new QueryParsingException(parseContext.index(), "[flt] query does not support [" + currentFieldName + "]");
}
} else if (token == XContentParser.Token.START_ARRAY) {
if ("fields".equals(currentFieldName)) {
- fields = Lists.newArrayList();
+ fields = Lists.newLinkedList();
while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
fields.add(parseContext.indexName(parser.text()));
}
@@ -112,13 +119,26 @@ public class FuzzyLikeThisQueryParser implements QueryParser {
FuzzyLikeThisQuery query = new FuzzyLikeThisQuery(maxNumTerms, analyzer);
if (fields == null) {
- // add the default _all field
- query.addTerms(likeText, parseContext.defaultField(), minSimilarity, prefixLength);
- } else {
- for (String field : fields) {
- query.addTerms(likeText, field, minSimilarity, prefixLength);
+ fields = Lists.newArrayList(parseContext.defaultField());
+ } else if (fields.isEmpty()) {
+ throw new QueryParsingException(parseContext.index(), "fuzzy_like_this requires 'fields' to be non-empty");
+ }
+ for (Iterator it = fields.iterator(); it.hasNext(); ) {
+ final String fieldName = it.next();
+ if (!Analysis.generatesCharacterTokenStream(analyzer, fieldName)) {
+ if (failOnUnsupportedField) {
+ throw new ElasticSearchIllegalArgumentException("more_like_this doesn't support binary/numeric fields: [" + fieldName + "]");
+ } else {
+ it.remove();
+ }
}
}
+ if (fields.isEmpty()) {
+ return null;
+ }
+ for (String field : fields) {
+ query.addTerms(likeText, field, minSimilarity, prefixLength);
+ }
query.setBoost(boost);
query.setIgnoreTF(ignoreTF);
diff --git a/src/main/java/org/elasticsearch/index/query/MoreLikeThisFieldQueryBuilder.java b/src/main/java/org/elasticsearch/index/query/MoreLikeThisFieldQueryBuilder.java
index 9130507d47f..bf5a3c18161 100644
--- a/src/main/java/org/elasticsearch/index/query/MoreLikeThisFieldQueryBuilder.java
+++ b/src/main/java/org/elasticsearch/index/query/MoreLikeThisFieldQueryBuilder.java
@@ -44,6 +44,7 @@ public class MoreLikeThisFieldQueryBuilder extends BaseQueryBuilder implements B
private float boostTerms = -1;
private float boost = -1;
private String analyzer;
+ private boolean failOnUnsupportedField;
/**
* A more like this query that runs against a specific field.
@@ -157,6 +158,14 @@ public class MoreLikeThisFieldQueryBuilder extends BaseQueryBuilder implements B
return this;
}
+ /**
+ * Whether to fail or return no result when this query is run against a field which is not supported such as binary/numeric fields.
+ */
+ public MoreLikeThisFieldQueryBuilder failOnUnsupportedField(boolean fail) {
+ failOnUnsupportedField = fail;
+ return this;
+ }
+
@Override
protected void doXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject(MoreLikeThisFieldQueryParser.NAME);
@@ -202,6 +211,9 @@ public class MoreLikeThisFieldQueryBuilder extends BaseQueryBuilder implements B
if (analyzer != null) {
builder.field("analyzer", analyzer);
}
+ if (!failOnUnsupportedField) {
+ builder.field("fail_on_unsupported_field", failOnUnsupportedField);
+ }
builder.endObject();
builder.endObject();
}
diff --git a/src/main/java/org/elasticsearch/index/query/MoreLikeThisFieldQueryParser.java b/src/main/java/org/elasticsearch/index/query/MoreLikeThisFieldQueryParser.java
index aa5af80a20a..6ad95c7f3a9 100644
--- a/src/main/java/org/elasticsearch/index/query/MoreLikeThisFieldQueryParser.java
+++ b/src/main/java/org/elasticsearch/index/query/MoreLikeThisFieldQueryParser.java
@@ -22,10 +22,12 @@ package org.elasticsearch.index.query;
import com.google.common.collect.Sets;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.search.Query;
+import org.elasticsearch.ElasticSearchIllegalArgumentException;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.lucene.search.MoreLikeThisQuery;
import org.elasticsearch.common.xcontent.XContentParser;
+import org.elasticsearch.index.analysis.Analysis;
import org.elasticsearch.index.mapper.MapperService;
import java.io.IOException;
@@ -65,6 +67,7 @@ public class MoreLikeThisFieldQueryParser implements QueryParser {
MoreLikeThisQuery mltQuery = new MoreLikeThisQuery();
mltQuery.setSimilarity(parseContext.searchSimilarity());
Analyzer analyzer = null;
+ boolean failOnUnsupportedField = true;
String currentFieldName = null;
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
@@ -94,6 +97,8 @@ public class MoreLikeThisFieldQueryParser implements QueryParser {
analyzer = parseContext.analysisService().analyzer(parser.text());
} else if ("boost".equals(currentFieldName)) {
mltQuery.setBoost(parser.floatValue());
+ } else if ("fail_on_unsupported_field".equals(currentFieldName) || "failOnUnsupportedField".equals(currentFieldName)) {
+ failOnUnsupportedField = parser.booleanValue();
} else {
throw new QueryParsingException(parseContext.index(), "[mlt_field] query does not support [" + currentFieldName + "]");
}
@@ -130,6 +135,13 @@ public class MoreLikeThisFieldQueryParser implements QueryParser {
if (analyzer == null) {
analyzer = parseContext.mapperService().searchAnalyzer();
}
+ if (!Analysis.generatesCharacterTokenStream(analyzer, fieldName)) {
+ if (failOnUnsupportedField) {
+ throw new ElasticSearchIllegalArgumentException("more_like_this_field doesn't support binary/numeric fields: [" + fieldName + "]");
+ } else {
+ return null;
+ }
+ }
mltQuery.setAnalyzer(analyzer);
mltQuery.setMoreLikeFields(new String[]{fieldName});
return wrapSmartNameQuery(mltQuery, smartNameFieldMappers, parseContext);
diff --git a/src/main/java/org/elasticsearch/index/query/MoreLikeThisQueryBuilder.java b/src/main/java/org/elasticsearch/index/query/MoreLikeThisQueryBuilder.java
index 2c07bc56bcb..adb68924401 100644
--- a/src/main/java/org/elasticsearch/index/query/MoreLikeThisQueryBuilder.java
+++ b/src/main/java/org/elasticsearch/index/query/MoreLikeThisQueryBuilder.java
@@ -45,6 +45,7 @@ public class MoreLikeThisQueryBuilder extends BaseQueryBuilder implements Boosta
private float boostTerms = -1;
private float boost = -1;
private String analyzer;
+ private boolean failOnUnsupportedField = true;
/**
* Constructs a new more like this query which uses the "_all" field.
@@ -165,6 +166,14 @@ public class MoreLikeThisQueryBuilder extends BaseQueryBuilder implements Boosta
return this;
}
+ /**
+ * Whether to fail or return no result when this query is run against a field which is not supported such as binary/numeric fields.
+ */
+ public MoreLikeThisQueryBuilder failOnUnsupportedField(boolean fail) {
+ failOnUnsupportedField = fail;
+ return this;
+ }
+
@Override
protected void doXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject(MoreLikeThisQueryParser.NAME);
@@ -216,6 +225,9 @@ public class MoreLikeThisQueryBuilder extends BaseQueryBuilder implements Boosta
if (analyzer != null) {
builder.field("analyzer", analyzer);
}
+ if (!failOnUnsupportedField) {
+ builder.field("fail_on_unsupported_field", failOnUnsupportedField);
+ }
builder.endObject();
}
}
\ No newline at end of file
diff --git a/src/main/java/org/elasticsearch/index/query/MoreLikeThisQueryParser.java b/src/main/java/org/elasticsearch/index/query/MoreLikeThisQueryParser.java
index 0a77a0ad2f4..48c476c619a 100644
--- a/src/main/java/org/elasticsearch/index/query/MoreLikeThisQueryParser.java
+++ b/src/main/java/org/elasticsearch/index/query/MoreLikeThisQueryParser.java
@@ -23,11 +23,15 @@ import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.search.Query;
+import org.elasticsearch.ElasticSearchIllegalArgumentException;
+import org.elasticsearch.common.Strings;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.lucene.search.MoreLikeThisQuery;
import org.elasticsearch.common.xcontent.XContentParser;
+import org.elasticsearch.index.analysis.Analysis;
import java.io.IOException;
+import java.util.Iterator;
import java.util.List;
import java.util.Set;
@@ -52,9 +56,10 @@ public class MoreLikeThisQueryParser implements QueryParser {
XContentParser parser = parseContext.parser();
MoreLikeThisQuery mltQuery = new MoreLikeThisQuery();
- mltQuery.setMoreLikeFields(new String[]{parseContext.defaultField()});
mltQuery.setSimilarity(parseContext.searchSimilarity());
Analyzer analyzer = null;
+ List moreLikeFields = null;
+ boolean failOnUnsupportedField = true;
XContentParser.Token token;
String currentFieldName = null;
@@ -85,6 +90,8 @@ public class MoreLikeThisQueryParser implements QueryParser {
analyzer = parseContext.analysisService().analyzer(parser.text());
} else if ("boost".equals(currentFieldName)) {
mltQuery.setBoost(parser.floatValue());
+ } else if ("fail_on_unsupported_field".equals(currentFieldName) || "failOnUnsupportedField".equals(currentFieldName)) {
+ failOnUnsupportedField = parser.booleanValue();
} else {
throw new QueryParsingException(parseContext.index(), "[mlt] query does not support [" + currentFieldName + "]");
}
@@ -96,11 +103,10 @@ public class MoreLikeThisQueryParser implements QueryParser {
}
mltQuery.setStopWords(stopWords);
} else if ("fields".equals(currentFieldName)) {
- List fields = Lists.newArrayList();
+ moreLikeFields = Lists.newLinkedList();
while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
- fields.add(parseContext.indexName(parser.text()));
+ moreLikeFields.add(parseContext.indexName(parser.text()));
}
- mltQuery.setMoreLikeFields(fields.toArray(new String[fields.size()]));
} else {
throw new QueryParsingException(parseContext.index(), "[mlt] query does not support [" + currentFieldName + "]");
}
@@ -110,15 +116,33 @@ public class MoreLikeThisQueryParser implements QueryParser {
if (mltQuery.getLikeText() == null) {
throw new QueryParsingException(parseContext.index(), "more_like_this requires 'like_text' to be specified");
}
- if (mltQuery.getMoreLikeFields() == null || mltQuery.getMoreLikeFields().length == 0) {
- throw new QueryParsingException(parseContext.index(), "more_like_this requires 'fields' to be specified");
- }
if (analyzer == null) {
analyzer = parseContext.mapperService().searchAnalyzer();
}
-
mltQuery.setAnalyzer(analyzer);
+
+ if (moreLikeFields == null) {
+ moreLikeFields = Lists.newArrayList(parseContext.defaultField());
+ } else if (moreLikeFields.isEmpty()) {
+ throw new QueryParsingException(parseContext.index(), "more_like_this requires 'fields' to be non-empty");
+ }
+
+ for (Iterator it = moreLikeFields.iterator(); it.hasNext(); ) {
+ final String fieldName = it.next();
+ if (!Analysis.generatesCharacterTokenStream(analyzer, fieldName)) {
+ if (failOnUnsupportedField) {
+ throw new ElasticSearchIllegalArgumentException("more_like_this doesn't support binary/numeric fields: [" + fieldName + "]");
+ } else {
+ it.remove();
+ }
+ }
+ }
+ if (moreLikeFields.isEmpty()) {
+ return null;
+ }
+ mltQuery.setMoreLikeFields(moreLikeFields.toArray(Strings.EMPTY_ARRAY));
+
return mltQuery;
}
}
\ No newline at end of file
diff --git a/src/test/java/org/elasticsearch/test/integration/flt/FuzzyLikeThisActionTests.java b/src/test/java/org/elasticsearch/test/integration/flt/FuzzyLikeThisActionTests.java
new file mode 100644
index 00000000000..e9876bbeab3
--- /dev/null
+++ b/src/test/java/org/elasticsearch/test/integration/flt/FuzzyLikeThisActionTests.java
@@ -0,0 +1,89 @@
+/*
+ * Licensed to ElasticSearch and Shay Banon under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. ElasticSearch licenses this
+ * file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.elasticsearch.test.integration.flt;
+
+import org.elasticsearch.action.search.SearchPhaseExecutionException;
+import org.elasticsearch.action.search.SearchResponse;
+import org.elasticsearch.test.integration.AbstractSharedClusterTest;
+import org.testng.annotations.Test;
+
+import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
+import static org.elasticsearch.index.query.QueryBuilders.fuzzyLikeThisFieldQuery;
+import static org.elasticsearch.index.query.QueryBuilders.fuzzyLikeThisQuery;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.equalTo;
+import static org.testng.Assert.fail;
+
+/**
+ *
+ */
+public class FuzzyLikeThisActionTests extends AbstractSharedClusterTest {
+
+ @Test
+ // See issue https://github.com/elasticsearch/elasticsearch/issues/3252
+ public void testNumericField() throws Exception {
+ prepareCreate("test").execute().actionGet();
+ ensureGreen();
+ client().prepareIndex("test", "type", "1")
+ .setSource(jsonBuilder().startObject().field("string_value", "lucene index").field("int_value", 1).endObject())
+ .execute().actionGet();
+ client().prepareIndex("test", "type", "2")
+ .setSource(jsonBuilder().startObject().field("string_value", "elasticsearch index").field("int_value", 42).endObject())
+ .execute().actionGet();
+
+ refresh();
+
+ // flt query with no field -> OK
+ SearchResponse searchResponse = client().prepareSearch().setQuery(fuzzyLikeThisQuery().likeText("index")).execute().actionGet();
+ assertThat(searchResponse.getFailedShards(), equalTo(0));
+ assertThat(searchResponse.getHits().getTotalHits(), equalTo(2L));
+
+ // flt query with string fields
+ searchResponse = client().prepareSearch().setQuery(fuzzyLikeThisQuery("string_value").likeText("index")).execute().actionGet();
+ assertThat(searchResponse.getFailedShards(), equalTo(0));
+ assertThat(searchResponse.getHits().getTotalHits(), equalTo(2L));
+
+ // flt query with at least a numeric field -> fail
+ try {
+ searchResponse = client().prepareSearch().setQuery(fuzzyLikeThisQuery("string_value", "int_value").likeText("index")).execute().actionGet();
+ fail();
+ } catch (SearchPhaseExecutionException e) {
+ // OK
+ }
+
+ // flt query with at least a numeric field but fail_on_unsupported_field set to false
+ searchResponse = client().prepareSearch().setQuery(fuzzyLikeThisQuery("string_value", "int_value").likeText("index").failOnUnsupportedField(false)).execute().actionGet();
+ assertThat(searchResponse.getFailedShards(), equalTo(0));
+ assertThat(searchResponse.getHits().getTotalHits(), equalTo(2L));
+
+ // flt field query on a numeric field -> failure
+ try {
+ searchResponse = client().prepareSearch().setQuery(fuzzyLikeThisFieldQuery("int_value").likeText("42")).execute().actionGet();
+ } catch (SearchPhaseExecutionException e) {
+ // OK
+ }
+
+ // flt field query on a numeric field but fail_on_unsupported_field set to false
+ searchResponse = client().prepareSearch().setQuery(fuzzyLikeThisFieldQuery("int_value").likeText("42").failOnUnsupportedField(false)).execute().actionGet();
+ assertThat(searchResponse.getFailedShards(), equalTo(0));
+ assertThat(searchResponse.getHits().getTotalHits(), equalTo(0L));
+ }
+
+}
diff --git a/src/test/java/org/elasticsearch/test/integration/mlt/MoreLikeThisActionTests.java b/src/test/java/org/elasticsearch/test/integration/mlt/MoreLikeThisActionTests.java
index a38fbc467d3..38dbcc92de0 100644
--- a/src/test/java/org/elasticsearch/test/integration/mlt/MoreLikeThisActionTests.java
+++ b/src/test/java/org/elasticsearch/test/integration/mlt/MoreLikeThisActionTests.java
@@ -19,17 +19,8 @@
package org.elasticsearch.test.integration.mlt;
-import static org.elasticsearch.client.Requests.indexAliasesRequest;
-import static org.elasticsearch.client.Requests.indexRequest;
-import static org.elasticsearch.client.Requests.moreLikeThisRequest;
-import static org.elasticsearch.client.Requests.refreshRequest;
-import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
-import static org.elasticsearch.index.query.FilterBuilders.termFilter;
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.equalTo;
-import static org.hamcrest.Matchers.notNullValue;
-
import org.elasticsearch.action.admin.cluster.health.ClusterHealthStatus;
+import org.elasticsearch.action.search.SearchPhaseExecutionException;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.Client;
import org.elasticsearch.common.settings.ImmutableSettings;
@@ -37,6 +28,16 @@ import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.test.integration.AbstractSharedClusterTest;
import org.testng.annotations.Test;
+import static org.elasticsearch.client.Requests.*;
+import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
+import static org.elasticsearch.index.query.FilterBuilders.termFilter;
+import static org.elasticsearch.index.query.QueryBuilders.moreLikeThisFieldQuery;
+import static org.elasticsearch.index.query.QueryBuilders.moreLikeThisQuery;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.testng.Assert.fail;
+
/**
*
*/
@@ -151,4 +152,67 @@ public class MoreLikeThisActionTests extends AbstractSharedClusterTest {
assertThat(searchResponse, notNullValue());
}
+ @Test
+ // See issue https://github.com/elasticsearch/elasticsearch/issues/3252
+ public void testNumericField() throws Exception {
+ prepareCreate("test").execute().actionGet();
+ ensureGreen();
+ client().prepareIndex("test", "type", "1")
+ .setSource(jsonBuilder().startObject().field("string_value", "lucene index").field("int_value", 1).endObject())
+ .execute().actionGet();
+ client().prepareIndex("test", "type", "2")
+ .setSource(jsonBuilder().startObject().field("string_value", "elasticsearch index").field("int_value", 42).endObject())
+ .execute().actionGet();
+
+ refresh();
+
+ // Implicit list of fields -> ignore numeric fields
+ SearchResponse searchResponse = client().prepareMoreLikeThis("test", "type", "1").setMinDocFreq(1).setMinTermFreq(1).execute().actionGet();
+ assertThat(searchResponse.getFailedShards(), equalTo(0));
+ assertThat(searchResponse.getHits().totalHits(), equalTo(1L));
+
+ // Explicit list of fields including numeric fields -> fail
+ try {
+ searchResponse = client().prepareMoreLikeThis("test", "type", "1").setField("string_value", "int_value").execute().actionGet();
+ fail();
+ } catch (SearchPhaseExecutionException e) {
+ // OK
+ }
+
+ // mlt query with no field -> OK
+ searchResponse = client().prepareSearch().setQuery(moreLikeThisQuery().likeText("index").minTermFreq(1).minDocFreq(1)).execute().actionGet();
+ assertThat(searchResponse.getFailedShards(), equalTo(0));
+ assertThat(searchResponse.getHits().getTotalHits(), equalTo(2L));
+
+ // mlt query with string fields
+ searchResponse = client().prepareSearch().setQuery(moreLikeThisQuery("string_value").likeText("index").minTermFreq(1).minDocFreq(1)).execute().actionGet();
+ assertThat(searchResponse.getFailedShards(), equalTo(0));
+ assertThat(searchResponse.getHits().getTotalHits(), equalTo(2L));
+
+ // mlt query with at least a numeric field -> fail
+ try {
+ searchResponse = client().prepareSearch().setQuery(moreLikeThisQuery("string_value", "int_value").likeText("index")).execute().actionGet();
+ fail();
+ } catch (SearchPhaseExecutionException e) {
+ // OK
+ }
+
+ // mlt query with at least a numeric field but fail_on_unsupported_field set to false
+ searchResponse = client().prepareSearch().setQuery(moreLikeThisQuery("string_value", "int_value").likeText("index").minTermFreq(1).minDocFreq(1).failOnUnsupportedField(false)).execute().actionGet();
+ assertThat(searchResponse.getFailedShards(), equalTo(0));
+ assertThat(searchResponse.getHits().getTotalHits(), equalTo(2L));
+
+ // mlt field query on a numeric field -> failure
+ try {
+ searchResponse = client().prepareSearch().setQuery(moreLikeThisFieldQuery("int_value").likeText("42").minTermFreq(1).minDocFreq(1)).execute().actionGet();
+ } catch (SearchPhaseExecutionException e) {
+ // OK
+ }
+
+ // mlt field query on a numeric field but fail_on_unsupported_field set to false
+ searchResponse = client().prepareSearch().setQuery(moreLikeThisFieldQuery("int_value").likeText("42").minTermFreq(1).minDocFreq(1).failOnUnsupportedField(false)).execute().actionGet();
+ assertThat(searchResponse.getFailedShards(), equalTo(0));
+ assertThat(searchResponse.getHits().getTotalHits(), equalTo(0L));
+ }
+
}
diff --git a/src/test/java/org/elasticsearch/test/unit/index/mapper/geo/LatLonMappingGeoPointTests.java b/src/test/java/org/elasticsearch/test/unit/index/mapper/geo/LatLonMappingGeoPointTests.java
index 891a805685f..8fdea387130 100644
--- a/src/test/java/org/elasticsearch/test/unit/index/mapper/geo/LatLonMappingGeoPointTests.java
+++ b/src/test/java/org/elasticsearch/test/unit/index/mapper/geo/LatLonMappingGeoPointTests.java
@@ -185,9 +185,9 @@ public class LatLonMappingGeoPointTests {
.bytes());
assertThat(doc.rootDoc().getField("point.lat"), notNullValue());
- assertThat(doc.rootDoc().getField("point.lat").numericValue(), nullValue());
+ assertThat(doc.rootDoc().getField("point.lat").fieldType().stored(), is(false));
assertThat(doc.rootDoc().getField("point.lon"), notNullValue());
- assertThat(doc.rootDoc().getField("point.lon").numericValue(), nullValue());
+ assertThat(doc.rootDoc().getField("point.lon").fieldType().stored(), is(false));
assertThat(doc.rootDoc().getField("point.geohash"), nullValue());
assertThat(doc.rootDoc().get("point"), equalTo("1.2,1.3"));
}