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
This commit is contained in:
parent
73c038fb48
commit
7f0115ba9a
|
@ -183,6 +183,7 @@ public class TransportMoreLikeThisAction extends TransportAction<MoreLikeThisReq
|
||||||
// exclude myself
|
// exclude myself
|
||||||
Term uidTerm = docMapper.uidMapper().term(request.type(), request.id());
|
Term uidTerm = docMapper.uidMapper().term(request.type(), request.id());
|
||||||
boolBuilder.mustNot(termQuery(uidTerm.field(), uidTerm.text()));
|
boolBuilder.mustNot(termQuery(uidTerm.field(), uidTerm.text()));
|
||||||
|
boolBuilder.adjustPureNegative(false);
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
listener.onFailure(e);
|
listener.onFailure(e);
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
package org.elasticsearch.index.query;
|
package org.elasticsearch.index.query;
|
||||||
|
|
||||||
|
import org.apache.lucene.search.MatchAllDocsQuery;
|
||||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -41,6 +42,8 @@ public class BoolQueryBuilder extends BaseQueryBuilder implements BoostableQuery
|
||||||
private Boolean disableCoord;
|
private Boolean disableCoord;
|
||||||
|
|
||||||
private String minimumShouldMatch;
|
private String minimumShouldMatch;
|
||||||
|
|
||||||
|
private Boolean adjustPureNegative;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a query that <b>must</b> appear in the matching documents.
|
* Adds a query that <b>must</b> appear in the matching documents.
|
||||||
|
@ -119,6 +122,16 @@ public class BoolQueryBuilder extends BaseQueryBuilder implements BoostableQuery
|
||||||
public boolean hasClauses() {
|
public boolean hasClauses() {
|
||||||
return !mustClauses.isEmpty() || !mustNotClauses.isEmpty() || !shouldClauses.isEmpty();
|
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 <code>true</code>.
|
||||||
|
*/
|
||||||
|
public BoolQueryBuilder adjustPureNegative(boolean adjustPureNegative) {
|
||||||
|
this.adjustPureNegative = adjustPureNegative;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doXContent(XContentBuilder builder, Params params) throws IOException {
|
protected void doXContent(XContentBuilder builder, Params params) throws IOException {
|
||||||
|
@ -135,6 +148,9 @@ public class BoolQueryBuilder extends BaseQueryBuilder implements BoostableQuery
|
||||||
if (minimumShouldMatch != null) {
|
if (minimumShouldMatch != null) {
|
||||||
builder.field("minimum_should_match", minimumShouldMatch);
|
builder.field("minimum_should_match", minimumShouldMatch);
|
||||||
}
|
}
|
||||||
|
if (adjustPureNegative != null) {
|
||||||
|
builder.field("adjust_pure_negative", adjustPureNegative);
|
||||||
|
}
|
||||||
builder.endObject();
|
builder.endObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -60,7 +60,7 @@ public class BoolQueryParser implements QueryParser {
|
||||||
String minimumShouldMatch = null;
|
String minimumShouldMatch = null;
|
||||||
|
|
||||||
List<BooleanClause> clauses = newArrayList();
|
List<BooleanClause> clauses = newArrayList();
|
||||||
|
boolean adjustPureNegative = true;
|
||||||
String currentFieldName = null;
|
String currentFieldName = null;
|
||||||
XContentParser.Token token;
|
XContentParser.Token token;
|
||||||
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
||||||
|
@ -119,6 +119,8 @@ public class BoolQueryParser implements QueryParser {
|
||||||
boost = parser.floatValue();
|
boost = parser.floatValue();
|
||||||
} else if ("minimum_number_should_match".equals(currentFieldName) || "minimumNumberShouldMatch".equals(currentFieldName)) {
|
} else if ("minimum_number_should_match".equals(currentFieldName) || "minimumNumberShouldMatch".equals(currentFieldName)) {
|
||||||
minimumShouldMatch = parser.textOrNull();
|
minimumShouldMatch = parser.textOrNull();
|
||||||
|
} else if ("adjust_pure_negative".equals(currentFieldName) || "adjustPureNegative".equals(currentFieldName)) {
|
||||||
|
adjustPureNegative = parser.booleanValue();
|
||||||
} else {
|
} else {
|
||||||
throw new QueryParsingException(parseContext.index(), "[bool] query does not support [" + currentFieldName + "]");
|
throw new QueryParsingException(parseContext.index(), "[bool] query does not support [" + currentFieldName + "]");
|
||||||
}
|
}
|
||||||
|
@ -135,6 +137,6 @@ public class BoolQueryParser implements QueryParser {
|
||||||
}
|
}
|
||||||
query.setBoost(boost);
|
query.setBoost(boost);
|
||||||
Queries.applyMinimumShouldMatch(query, minimumShouldMatch);
|
Queries.applyMinimumShouldMatch(query, minimumShouldMatch);
|
||||||
return optimizeQuery(fixNegativeQueryIfNeeded(query));
|
return optimizeQuery(adjustPureNegative ? fixNegativeQueryIfNeeded(query) : query);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,6 +58,27 @@ public class MoreLikeThisActionTests extends AbstractSharedClusterTest {
|
||||||
SearchResponse mltResponse = client().moreLikeThis(moreLikeThisRequest("test").type("type1").id("1").minTermFreq(1).minDocFreq(1)).actionGet();
|
SearchResponse mltResponse = client().moreLikeThis(moreLikeThisRequest("test").type("type1").id("1").minTermFreq(1).minDocFreq(1)).actionGet();
|
||||||
assertHitCount(mltResponse, 1l);
|
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
|
@Test
|
||||||
|
|
Loading…
Reference in New Issue