From 7f0115ba9ac98921d585597a4cf78bda8ec3c8d1 Mon Sep 17 00:00:00 2001 From: Simon Willnauer Date: Wed, 7 Aug 2013 12:16:27 +0200 Subject: [PATCH] Return nothing instead of everything in MLT if no field is supported. Today due the optimizations in the boolean query builder we adjust a pure negative query with a 'match_all'. This is not the desired behavior in the MLT API if all the fields in a document are unsupported. If that happens today we return all documents but the one MLT is executed on. Closes #3453 --- .../mlt/TransportMoreLikeThisAction.java | 1 + .../index/query/BoolQueryBuilder.java | 16 ++++++++++++++ .../index/query/BoolQueryParser.java | 6 ++++-- .../mlt/MoreLikeThisActionTests.java | 21 +++++++++++++++++++ 4 files changed, 42 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/elasticsearch/action/mlt/TransportMoreLikeThisAction.java b/src/main/java/org/elasticsearch/action/mlt/TransportMoreLikeThisAction.java index 808c6077364..69bd6a50d75 100644 --- a/src/main/java/org/elasticsearch/action/mlt/TransportMoreLikeThisAction.java +++ b/src/main/java/org/elasticsearch/action/mlt/TransportMoreLikeThisAction.java @@ -183,6 +183,7 @@ public class TransportMoreLikeThisAction extends TransportActionmust appear in the matching documents. @@ -119,6 +122,16 @@ public class BoolQueryBuilder extends BaseQueryBuilder implements BoostableQuery public boolean hasClauses() { return !mustClauses.isEmpty() || !mustNotClauses.isEmpty() || !shouldClauses.isEmpty(); } + + /** + * If a boolean query contains only negative ("must not") clauses should the + * BooleanQuery be enhanced with a {@link MatchAllDocsQuery} in order to act + * as a pure exclude. The default is true. + */ + public BoolQueryBuilder adjustPureNegative(boolean adjustPureNegative) { + this.adjustPureNegative = adjustPureNegative; + return this; + } @Override protected void doXContent(XContentBuilder builder, Params params) throws IOException { @@ -135,6 +148,9 @@ public class BoolQueryBuilder extends BaseQueryBuilder implements BoostableQuery if (minimumShouldMatch != null) { builder.field("minimum_should_match", minimumShouldMatch); } + if (adjustPureNegative != null) { + builder.field("adjust_pure_negative", adjustPureNegative); + } builder.endObject(); } diff --git a/src/main/java/org/elasticsearch/index/query/BoolQueryParser.java b/src/main/java/org/elasticsearch/index/query/BoolQueryParser.java index e35468819e9..49cb1300d7a 100644 --- a/src/main/java/org/elasticsearch/index/query/BoolQueryParser.java +++ b/src/main/java/org/elasticsearch/index/query/BoolQueryParser.java @@ -60,7 +60,7 @@ public class BoolQueryParser implements QueryParser { String minimumShouldMatch = null; List clauses = newArrayList(); - + boolean adjustPureNegative = true; String currentFieldName = null; XContentParser.Token token; while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { @@ -119,6 +119,8 @@ public class BoolQueryParser implements QueryParser { boost = parser.floatValue(); } else if ("minimum_number_should_match".equals(currentFieldName) || "minimumNumberShouldMatch".equals(currentFieldName)) { minimumShouldMatch = parser.textOrNull(); + } else if ("adjust_pure_negative".equals(currentFieldName) || "adjustPureNegative".equals(currentFieldName)) { + adjustPureNegative = parser.booleanValue(); } else { throw new QueryParsingException(parseContext.index(), "[bool] query does not support [" + currentFieldName + "]"); } @@ -135,6 +137,6 @@ public class BoolQueryParser implements QueryParser { } query.setBoost(boost); Queries.applyMinimumShouldMatch(query, minimumShouldMatch); - return optimizeQuery(fixNegativeQueryIfNeeded(query)); + return optimizeQuery(adjustPureNegative ? fixNegativeQueryIfNeeded(query) : query); } } 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 6f72a20aea5..332d3d70a6b 100644 --- a/src/test/java/org/elasticsearch/test/integration/mlt/MoreLikeThisActionTests.java +++ b/src/test/java/org/elasticsearch/test/integration/mlt/MoreLikeThisActionTests.java @@ -58,6 +58,27 @@ public class MoreLikeThisActionTests extends AbstractSharedClusterTest { SearchResponse mltResponse = client().moreLikeThis(moreLikeThisRequest("test").type("type1").id("1").minTermFreq(1).minDocFreq(1)).actionGet(); assertHitCount(mltResponse, 1l); } + + + @Test + public void testSimpleMoreLikeOnLongField() throws Exception { + logger.info("Creating index test"); + createIndex("test"); + logger.info("Running Cluster Health"); + assertThat(ensureGreen(), equalTo(ClusterHealthStatus.GREEN)); + + logger.info("Indexing..."); + client().index(indexRequest("test").type("type1").id("1").source(jsonBuilder().startObject().field("some_long", 1367484649580l).endObject())).actionGet(); + client().index(indexRequest("test").type("type2").id("2").source(jsonBuilder().startObject().field("some_long", 0).endObject())).actionGet(); + client().index(indexRequest("test").type("type1").id("3").source(jsonBuilder().startObject().field("some_long", -666).endObject())).actionGet(); + + + client().admin().indices().refresh(refreshRequest()).actionGet(); + + logger.info("Running moreLikeThis"); + SearchResponse mltResponse = client().moreLikeThis(moreLikeThisRequest("test").type("type1").id("1").minTermFreq(1).minDocFreq(1)).actionGet(); + assertHitCount(mltResponse, 0l); + } @Test