SQL: Preserve scoring in bool queries (#30730)

Make all bool constructs use match/should (that is a query context) as
that is controlled and changed to a filter context by ES automatically
based on the sort order (_doc, field vs _sort) and trackScores.

Fix #29685
This commit is contained in:
Costin Leau 2018-05-21 21:50:06 +03:00 committed by GitHub
parent be8c0f27be
commit dcf0f9f8dd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 33 additions and 31 deletions

View File

@ -5,8 +5,6 @@
*/ */
package org.elasticsearch.xpack.sql.execution.search; package org.elasticsearch.xpack.sql.execution.search;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.ConstantScoreQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder; import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.search.aggregations.AggregationBuilder; import org.elasticsearch.search.aggregations.AggregationBuilder;
import org.elasticsearch.search.aggregations.bucket.composite.CompositeAggregationBuilder; import org.elasticsearch.search.aggregations.bucket.composite.CompositeAggregationBuilder;
@ -28,6 +26,7 @@ import org.elasticsearch.xpack.sql.querydsl.container.Sort;
import java.util.List; import java.util.List;
import static java.util.Collections.singletonList; import static java.util.Collections.singletonList;
import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
import static org.elasticsearch.search.sort.SortBuilders.fieldSort; import static org.elasticsearch.search.sort.SortBuilders.fieldSort;
import static org.elasticsearch.search.sort.SortBuilders.scoreSort; import static org.elasticsearch.search.sort.SortBuilders.scoreSort;
import static org.elasticsearch.search.sort.SortBuilders.scriptSort; import static org.elasticsearch.search.sort.SortBuilders.scriptSort;
@ -37,20 +36,23 @@ public abstract class SourceGenerator {
private static final List<String> NO_STORED_FIELD = singletonList(StoredFieldsContext._NONE_); private static final List<String> NO_STORED_FIELD = singletonList(StoredFieldsContext._NONE_);
public static SearchSourceBuilder sourceBuilder(QueryContainer container, QueryBuilder filter, Integer size) { public static SearchSourceBuilder sourceBuilder(QueryContainer container, QueryBuilder filter, Integer size) {
final SearchSourceBuilder source = new SearchSourceBuilder(); QueryBuilder finalQuery = null;
// add the source // add the source
if (container.query() == null) { if (container.query() != null) {
if (filter != null) { if (filter != null) {
source.query(new ConstantScoreQueryBuilder(filter)); finalQuery = boolQuery().must(container.query().asBuilder()).filter(filter);
} else {
finalQuery = container.query().asBuilder();
} }
} else { } else {
if (filter != null) { if (filter != null) {
source.query(new BoolQueryBuilder().must(container.query().asBuilder()).filter(filter)); finalQuery = boolQuery().filter(filter);
} else {
source.query(container.query().asBuilder());
} }
} }
final SearchSourceBuilder source = new SearchSourceBuilder();
source.query(finalQuery);
SqlSourceBuilder sortBuilder = new SqlSourceBuilder(); SqlSourceBuilder sortBuilder = new SqlSourceBuilder();
// Iterate through all the columns requested, collecting the fields that // Iterate through all the columns requested, collecting the fields that
// need to be retrieved from the result documents // need to be retrieved from the result documents

View File

@ -5,13 +5,13 @@
*/ */
package org.elasticsearch.xpack.sql.querydsl.query; package org.elasticsearch.xpack.sql.querydsl.query;
import java.util.Objects;
import org.elasticsearch.index.query.BoolQueryBuilder; import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder; import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.search.sort.NestedSortBuilder; import org.elasticsearch.search.sort.NestedSortBuilder;
import org.elasticsearch.xpack.sql.tree.Location; import org.elasticsearch.xpack.sql.tree.Location;
import java.util.Objects;
import static org.elasticsearch.index.query.QueryBuilders.boolQuery; import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
/** /**
@ -63,9 +63,8 @@ public class BoolQuery extends Query {
public QueryBuilder asBuilder() { public QueryBuilder asBuilder() {
BoolQueryBuilder boolQuery = boolQuery(); BoolQueryBuilder boolQuery = boolQuery();
if (isAnd) { if (isAnd) {
// TODO are we throwing out score by using filter? boolQuery.must(left.asBuilder());
boolQuery.filter(left.asBuilder()); boolQuery.must(right.asBuilder());
boolQuery.filter(right.asBuilder());
} else { } else {
boolQuery.should(left.asBuilder()); boolQuery.should(left.asBuilder());
boolQuery.should(right.asBuilder()); boolQuery.should(right.asBuilder());

View File

@ -5,9 +5,6 @@
*/ */
package org.elasticsearch.xpack.sql.execution.search; package org.elasticsearch.xpack.sql.execution.search;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.ConstantScoreQueryBuilder;
import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.index.query.Operator; import org.elasticsearch.index.query.Operator;
import org.elasticsearch.index.query.QueryBuilder; import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.search.aggregations.AggregatorFactories.Builder; import org.elasticsearch.search.aggregations.AggregatorFactories.Builder;
@ -28,6 +25,8 @@ import org.elasticsearch.xpack.sql.tree.Location;
import org.elasticsearch.xpack.sql.type.KeywordEsField; import org.elasticsearch.xpack.sql.type.KeywordEsField;
import static java.util.Collections.singletonList; import static java.util.Collections.singletonList;
import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
import static org.elasticsearch.index.query.QueryBuilders.matchQuery;
import static org.elasticsearch.search.sort.SortBuilders.fieldSort; import static org.elasticsearch.search.sort.SortBuilders.fieldSort;
import static org.elasticsearch.search.sort.SortBuilders.scoreSort; import static org.elasticsearch.search.sort.SortBuilders.scoreSort;
@ -42,22 +41,22 @@ public class SourceGeneratorTests extends ESTestCase {
public void testQueryNoFilter() { public void testQueryNoFilter() {
QueryContainer container = new QueryContainer().with(new MatchQuery(Location.EMPTY, "foo", "bar")); QueryContainer container = new QueryContainer().with(new MatchQuery(Location.EMPTY, "foo", "bar"));
SearchSourceBuilder sourceBuilder = SourceGenerator.sourceBuilder(container, null, randomIntBetween(1, 10)); SearchSourceBuilder sourceBuilder = SourceGenerator.sourceBuilder(container, null, randomIntBetween(1, 10));
assertEquals(new MatchQueryBuilder("foo", "bar").operator(Operator.OR), sourceBuilder.query()); assertEquals(matchQuery("foo", "bar").operator(Operator.OR), sourceBuilder.query());
} }
public void testNoQueryFilter() { public void testNoQueryFilter() {
QueryContainer container = new QueryContainer(); QueryContainer container = new QueryContainer();
QueryBuilder filter = new MatchQueryBuilder("bar", "baz"); QueryBuilder filter = matchQuery("bar", "baz");
SearchSourceBuilder sourceBuilder = SourceGenerator.sourceBuilder(container, filter, randomIntBetween(1, 10)); SearchSourceBuilder sourceBuilder = SourceGenerator.sourceBuilder(container, filter, randomIntBetween(1, 10));
assertEquals(new ConstantScoreQueryBuilder(new MatchQueryBuilder("bar", "baz")), sourceBuilder.query()); assertEquals(boolQuery().filter(matchQuery("bar", "baz")), sourceBuilder.query());
} }
public void testQueryFilter() { public void testQueryFilter() {
QueryContainer container = new QueryContainer().with(new MatchQuery(Location.EMPTY, "foo", "bar")); QueryContainer container = new QueryContainer().with(new MatchQuery(Location.EMPTY, "foo", "bar"));
QueryBuilder filter = new MatchQueryBuilder("bar", "baz"); QueryBuilder filter = matchQuery("bar", "baz");
SearchSourceBuilder sourceBuilder = SourceGenerator.sourceBuilder(container, filter, randomIntBetween(1, 10)); SearchSourceBuilder sourceBuilder = SourceGenerator.sourceBuilder(container, filter, randomIntBetween(1, 10));
assertEquals(new BoolQueryBuilder().must(new MatchQueryBuilder("foo", "bar").operator(Operator.OR)) assertEquals(boolQuery().must(matchQuery("foo", "bar").operator(Operator.OR)).filter(matchQuery("bar", "baz")),
.filter(new MatchQueryBuilder("bar", "baz")), sourceBuilder.query()); sourceBuilder.query());
} }
public void testLimit() { public void testLimit() {

View File

@ -16,7 +16,6 @@ import org.elasticsearch.client.Request;
import org.elasticsearch.client.Response; import org.elasticsearch.client.Response;
import org.elasticsearch.client.ResponseException; import org.elasticsearch.client.ResponseException;
import org.elasticsearch.common.CheckedSupplier; import org.elasticsearch.common.CheckedSupplier;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.collect.Tuple; import org.elasticsearch.common.collect.Tuple;
import org.elasticsearch.common.io.Streams; import org.elasticsearch.common.io.Streams;
import org.elasticsearch.common.xcontent.XContentHelper; import org.elasticsearch.common.xcontent.XContentHelper;
@ -33,12 +32,11 @@ import java.nio.charset.StandardCharsets;
import java.sql.JDBCType; import java.sql.JDBCType;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.TreeMap;
import static java.util.Collections.emptyList; import static java.util.Collections.emptyList;
import static java.util.Collections.emptyMap;
import static java.util.Collections.singletonList; import static java.util.Collections.singletonList;
import static java.util.Collections.singletonMap; import static java.util.Collections.singletonMap;
import static java.util.Collections.unmodifiableMap; import static java.util.Collections.unmodifiableMap;
@ -396,19 +394,23 @@ public abstract class RestSqlTestCase extends ESRestTestCase implements ErrorsTe
assertNotNull(query); assertNotNull(query);
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
Map<String, Object> constantScore = (Map<String, Object>) query.get("constant_score"); Map<String, Object> bool = (Map<String, Object>) query.get("bool");
assertNotNull(constantScore); assertNotNull(bool);
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
Map<String, Object> filter = (Map<String, Object>) constantScore.get("filter"); List<Object> filter = (List<Object>) bool.get("filter");
assertNotNull(filter); assertNotNull(filter);
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
Map<String, Object> match = (Map<String, Object>) filter.get("match"); Map<String, Object> map = (Map<String, Object>) filter.get(0);
assertNotNull(match); assertNotNull(map);
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
Map<String, Object> matchQuery = (Map<String, Object>) match.get("test"); Map<String, Object> matchQ = (Map<String, Object>) map.get("match");
@SuppressWarnings("unchecked")
Map<String, Object> matchQuery = (Map<String, Object>) matchQ.get("test");
assertNotNull(matchQuery); assertNotNull(matchQuery);
assertEquals("foo", matchQuery.get("query")); assertEquals("foo", matchQuery.get("query"));
} }