Split NestedQueryParser into toQuery and formXContent
This commit splits NestedQueryParser into toQuery and fromXContent. Relates to #10217
This commit is contained in:
parent
1dc985a2c4
commit
8d2a2f8d66
|
@ -19,43 +19,69 @@
|
|||
|
||||
package org.elasticsearch.index.query;
|
||||
|
||||
import org.apache.lucene.search.Filter;
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.apache.lucene.search.join.BitSetProducer;
|
||||
import org.apache.lucene.search.join.ScoreMode;
|
||||
import org.apache.lucene.search.join.ToParentBlockJoinQuery;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
import org.elasticsearch.common.lucene.search.Queries;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.index.mapper.object.ObjectMapper;
|
||||
import org.elasticsearch.index.query.support.QueryInnerHits;
|
||||
import org.elasticsearch.search.fetch.innerhits.InnerHitsContext;
|
||||
import org.elasticsearch.search.fetch.innerhits.InnerHitsSubSearchContext;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
|
||||
public class NestedQueryBuilder extends AbstractQueryBuilder<NestedQueryBuilder> {
|
||||
|
||||
/**
|
||||
* The default score move for nested queries.
|
||||
*/
|
||||
public static final ScoreMode DEFAULT_SCORE_MODE = ScoreMode.Avg;
|
||||
|
||||
/**
|
||||
* The queries name used while parsing
|
||||
*/
|
||||
public static final String NAME = "nested";
|
||||
|
||||
private final QueryBuilder queryBuilder;
|
||||
private final QueryBuilder query;
|
||||
|
||||
private final String path;
|
||||
|
||||
private String scoreMode;
|
||||
private ScoreMode scoreMode = DEFAULT_SCORE_MODE;
|
||||
|
||||
private QueryInnerHits innerHit;
|
||||
private QueryInnerHits queryInnerHits;
|
||||
|
||||
static final NestedQueryBuilder PROTOTYPE = new NestedQueryBuilder();
|
||||
|
||||
public NestedQueryBuilder(String path, QueryBuilder queryBuilder) {
|
||||
public NestedQueryBuilder(String path, QueryBuilder query) {
|
||||
if (path == null) {
|
||||
throw new IllegalArgumentException("[" + NAME + "] requires 'path' field");
|
||||
}
|
||||
if (query == null) {
|
||||
throw new IllegalArgumentException("[" + NAME + "] requires 'query' field");
|
||||
}
|
||||
this.path = path;
|
||||
this.queryBuilder = Objects.requireNonNull(queryBuilder);
|
||||
this.query = query;
|
||||
}
|
||||
|
||||
public NestedQueryBuilder(String path, QueryBuilder query, ScoreMode scoreMode, QueryInnerHits queryInnerHits) {
|
||||
this(path, query);
|
||||
scoreMode(scoreMode);
|
||||
this.queryInnerHits = queryInnerHits;
|
||||
}
|
||||
|
||||
/**
|
||||
* private constructor only used internally
|
||||
* The score mode how the scores from the matching child documents are mapped into the nested parent document.
|
||||
*/
|
||||
private NestedQueryBuilder() {
|
||||
this.path = null;
|
||||
this.queryBuilder = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The score mode.
|
||||
*/
|
||||
public NestedQueryBuilder scoreMode(String scoreMode) {
|
||||
public NestedQueryBuilder scoreMode(ScoreMode scoreMode) {
|
||||
if (scoreMode == null) {
|
||||
throw new IllegalArgumentException("[" + NAME + "] requires 'score_mode' field");
|
||||
}
|
||||
this.scoreMode = scoreMode;
|
||||
return this;
|
||||
}
|
||||
|
@ -64,22 +90,43 @@ public class NestedQueryBuilder extends AbstractQueryBuilder<NestedQueryBuilder>
|
|||
* Sets inner hit definition in the scope of this nested query and reusing the defined path and query.
|
||||
*/
|
||||
public NestedQueryBuilder innerHit(QueryInnerHits innerHit) {
|
||||
this.innerHit = innerHit;
|
||||
this.queryInnerHits = innerHit;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the nested query to execute.
|
||||
*/
|
||||
public QueryBuilder query() {
|
||||
return query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns inner hit definition in the scope of this query and reusing the defined type and query.
|
||||
*/
|
||||
public QueryInnerHits innerHit() {
|
||||
return queryInnerHits;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns how the scores from the matching child documents are mapped into the nested parent document.
|
||||
*/
|
||||
public ScoreMode scoreMode() {
|
||||
return scoreMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
builder.startObject(NAME);
|
||||
builder.field("query");
|
||||
queryBuilder.toXContent(builder, params);
|
||||
query.toXContent(builder, params);
|
||||
builder.field("path", path);
|
||||
if (scoreMode != null) {
|
||||
builder.field("score_mode", scoreMode);
|
||||
builder.field("score_mode", scoreMode.name().toLowerCase(Locale.ROOT));
|
||||
}
|
||||
printBoostAndQueryName(builder);
|
||||
if (innerHit != null) {
|
||||
innerHit.toXContent(builder, params);
|
||||
if (queryInnerHits != null) {
|
||||
queryInnerHits.toXContent(builder, params);
|
||||
}
|
||||
builder.endObject();
|
||||
}
|
||||
|
@ -88,4 +135,95 @@ public class NestedQueryBuilder extends AbstractQueryBuilder<NestedQueryBuilder>
|
|||
public final String getWriteableName() {
|
||||
return NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean doEquals(NestedQueryBuilder that) {
|
||||
return Objects.equals(query, that.query)
|
||||
&& Objects.equals(path, that.path)
|
||||
&& Objects.equals(scoreMode, that.scoreMode)
|
||||
&& Objects.equals(queryInnerHits, that.queryInnerHits);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int doHashCode() {
|
||||
return Objects.hash(query, path, scoreMode, queryInnerHits);
|
||||
}
|
||||
|
||||
private NestedQueryBuilder(StreamInput in) throws IOException {
|
||||
path = in.readString();
|
||||
final int ordinal = in.readVInt();
|
||||
scoreMode = ScoreMode.values()[ordinal];
|
||||
query = in.readQuery();
|
||||
if (in.readBoolean()) {
|
||||
queryInnerHits = new QueryInnerHits(in);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doWriteTo(StreamOutput out) throws IOException {
|
||||
out.writeString(path);
|
||||
out.writeVInt(scoreMode.ordinal());
|
||||
out.writeQuery(query);
|
||||
if (queryInnerHits != null) {
|
||||
out.writeBoolean(true);
|
||||
queryInnerHits.writeTo(out);
|
||||
} else {
|
||||
out.writeBoolean(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected NestedQueryBuilder doReadFrom(StreamInput in) throws IOException {
|
||||
return new NestedQueryBuilder(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Query doToQuery(QueryShardContext context) throws IOException {
|
||||
ObjectMapper nestedObjectMapper = context.getObjectMapper(path);
|
||||
if (nestedObjectMapper == null) {
|
||||
throw new IllegalStateException("[" + NAME + "] failed to find nested object under path [" + path + "]");
|
||||
}
|
||||
if (!nestedObjectMapper.nested().isNested()) {
|
||||
throw new IllegalStateException("[" + NAME + "] nested object under path [" + path + "] is not of nested type");
|
||||
}
|
||||
final BitSetProducer parentFilter;
|
||||
final Filter childFilter;
|
||||
final ObjectMapper parentObjectMapper;
|
||||
final Query innerQuery;
|
||||
ObjectMapper objectMapper = context.nestedScope().getObjectMapper();
|
||||
try {
|
||||
if (objectMapper == null) {
|
||||
parentFilter = context.bitsetFilter(Queries.newNonNestedFilter());
|
||||
} else {
|
||||
parentFilter = context.bitsetFilter(objectMapper.nestedTypeFilter());
|
||||
}
|
||||
childFilter = nestedObjectMapper.nestedTypeFilter();
|
||||
parentObjectMapper = context.nestedScope().nextLevel(nestedObjectMapper);
|
||||
innerQuery = this.query.toQuery(context);
|
||||
if (innerQuery == null) {
|
||||
return null;
|
||||
}
|
||||
} finally {
|
||||
context.nestedScope().previousLevel();
|
||||
}
|
||||
|
||||
if (queryInnerHits != null) {
|
||||
try (XContentParser parser = queryInnerHits.getXcontentParser()) {
|
||||
XContentParser.Token token = parser.nextToken();
|
||||
if (token != XContentParser.Token.START_OBJECT) {
|
||||
throw new IllegalStateException("start object expected but was: [" + token + "]");
|
||||
}
|
||||
InnerHitsSubSearchContext innerHits = context.indexQueryParserService().getInnerHitsQueryParserHelper().parse(parser);
|
||||
if (innerHits != null) {
|
||||
ParsedQuery parsedQuery = new ParsedQuery(innerQuery, context.copyNamedQueries());
|
||||
|
||||
InnerHitsContext.NestedInnerHits nestedInnerHits = new InnerHitsContext.NestedInnerHits(innerHits.getSubSearchContext(), parsedQuery, null, parentObjectMapper, nestedObjectMapper);
|
||||
String name = innerHits.getName() != null ? innerHits.getName() : path;
|
||||
context.addInnerHits(name, nestedInnerHits);
|
||||
}
|
||||
}
|
||||
}
|
||||
return new ToParentBlockJoinQuery(Queries.filtered(innerQuery, childFilter), parentFilter, scoreMode);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -31,21 +31,17 @@ import org.elasticsearch.common.lucene.search.Queries;
|
|||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.index.query.support.InnerHitsQueryParserHelper;
|
||||
import org.elasticsearch.index.query.support.NestedInnerQueryParseSupport;
|
||||
import org.elasticsearch.index.query.support.QueryInnerHits;
|
||||
import org.elasticsearch.search.fetch.innerhits.InnerHitsContext;
|
||||
import org.elasticsearch.search.fetch.innerhits.InnerHitsSubSearchContext;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class NestedQueryParser extends BaseQueryParserTemp {
|
||||
public class NestedQueryParser extends BaseQueryParser<NestedQueryBuilder> {
|
||||
|
||||
private static final ParseField FILTER_FIELD = new ParseField("filter").withAllDeprecated("query");
|
||||
private static final NestedQueryBuilder PROTOTYPE = new NestedQueryBuilder("", EmptyQueryBuilder.PROTOTYPE);
|
||||
|
||||
private final InnerHitsQueryParserHelper innerHitsQueryParserHelper;
|
||||
|
||||
@Inject
|
||||
public NestedQueryParser(InnerHitsQueryParserHelper innerHitsQueryParserHelper) {
|
||||
this.innerHitsQueryParserHelper = innerHitsQueryParserHelper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] names() {
|
||||
|
@ -53,33 +49,32 @@ public class NestedQueryParser extends BaseQueryParserTemp {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Query parse(QueryShardContext context) throws IOException, QueryParsingException {
|
||||
QueryParseContext parseContext = context.parseContext();
|
||||
public NestedQueryBuilder fromXContent(QueryParseContext parseContext) throws IOException, QueryParsingException {
|
||||
XContentParser parser = parseContext.parser();
|
||||
final ToBlockJoinQueryBuilder builder = new ToBlockJoinQueryBuilder(context);
|
||||
|
||||
float boost = AbstractQueryBuilder.DEFAULT_BOOST;
|
||||
ScoreMode scoreMode = ScoreMode.Avg;
|
||||
ScoreMode scoreMode = NestedQueryBuilder.DEFAULT_SCORE_MODE;
|
||||
String queryName = null;
|
||||
|
||||
QueryBuilder query = null;
|
||||
String path = null;
|
||||
String currentFieldName = null;
|
||||
QueryInnerHits queryInnerHits = null;
|
||||
XContentParser.Token token;
|
||||
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
||||
if (token == XContentParser.Token.FIELD_NAME) {
|
||||
currentFieldName = parser.currentName();
|
||||
} else if (token == XContentParser.Token.START_OBJECT) {
|
||||
if ("query".equals(currentFieldName)) {
|
||||
builder.query();
|
||||
query = parseContext.parseInnerQueryBuilder();
|
||||
} else if (parseContext.parseFieldMatcher().match(currentFieldName, FILTER_FIELD)) {
|
||||
builder.filter();
|
||||
query = parseContext.parseInnerFilterToQueryBuilder();
|
||||
} else if ("inner_hits".equals(currentFieldName)) {
|
||||
builder.setInnerHits(innerHitsQueryParserHelper.parse(parser));
|
||||
queryInnerHits = new QueryInnerHits(parser);
|
||||
} else {
|
||||
throw new QueryParsingException(parseContext, "[nested] query does not support [" + currentFieldName + "]");
|
||||
}
|
||||
} else if (token.isValue()) {
|
||||
if ("path".equals(currentFieldName)) {
|
||||
builder.setPath(parser.text());
|
||||
path = parser.text();
|
||||
} else if ("boost".equals(currentFieldName)) {
|
||||
boost = parser.floatValue();
|
||||
} else if ("score_mode".equals(currentFieldName) || "scoreMode".equals(currentFieldName)) {
|
||||
|
@ -104,69 +99,11 @@ public class NestedQueryParser extends BaseQueryParserTemp {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
builder.setScoreMode(scoreMode);
|
||||
ToParentBlockJoinQuery joinQuery = builder.build();
|
||||
if (joinQuery != null) {
|
||||
joinQuery.setBoost(boost);
|
||||
if (queryName != null) {
|
||||
context.addNamedQuery(queryName, joinQuery);
|
||||
}
|
||||
}
|
||||
return joinQuery;
|
||||
}
|
||||
|
||||
public static class ToBlockJoinQueryBuilder extends NestedInnerQueryParseSupport {
|
||||
|
||||
private ScoreMode scoreMode;
|
||||
private InnerHitsSubSearchContext innerHits;
|
||||
|
||||
public ToBlockJoinQueryBuilder(QueryShardContext context) throws IOException {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public void setScoreMode(ScoreMode scoreMode) {
|
||||
this.scoreMode = scoreMode;
|
||||
}
|
||||
|
||||
public void setInnerHits(InnerHitsSubSearchContext innerHits) {
|
||||
this.innerHits = innerHits;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ToParentBlockJoinQuery build() throws IOException {
|
||||
Query innerQuery;
|
||||
if (queryFound) {
|
||||
innerQuery = getInnerQuery();
|
||||
} else if (filterFound) {
|
||||
Query innerFilter = getInnerFilter();
|
||||
if (innerFilter != null) {
|
||||
innerQuery = new ConstantScoreQuery(getInnerFilter());
|
||||
} else {
|
||||
innerQuery = null;
|
||||
}
|
||||
} else {
|
||||
throw new QueryShardException(shardContext, "[nested] requires either 'query' or 'filter' field");
|
||||
}
|
||||
|
||||
if (innerHits != null) {
|
||||
ParsedQuery parsedQuery = new ParsedQuery(innerQuery, shardContext.copyNamedQueries());
|
||||
InnerHitsContext.NestedInnerHits nestedInnerHits = new InnerHitsContext.NestedInnerHits(innerHits.getSubSearchContext(), parsedQuery, null, getParentObjectMapper(), nestedObjectMapper);
|
||||
String name = innerHits.getName() != null ? innerHits.getName() : path;
|
||||
shardContext.addInnerHits(name, nestedInnerHits);
|
||||
}
|
||||
|
||||
if (innerQuery != null) {
|
||||
return new ToParentBlockJoinQuery(Queries.filtered(innerQuery, childFilter), parentFilter, scoreMode);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return new NestedQueryBuilder(path, query, scoreMode, queryInnerHits).queryName(queryName).boost(boost);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NestedQueryBuilder getBuilderPrototype() {
|
||||
return NestedQueryBuilder.PROTOTYPE;
|
||||
return PROTOTYPE;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -115,7 +115,7 @@ public class QueryShardContext {
|
|||
return parseFieldMatcher;
|
||||
}
|
||||
|
||||
private void reset() {
|
||||
public void reset() {
|
||||
allowUnmappedFields = indexQueryParser.defaultAllowUnmappedFields();
|
||||
this.parseFieldMatcher = ParseFieldMatcher.EMPTY;
|
||||
this.lookup = null;
|
||||
|
|
|
@ -448,6 +448,7 @@ public abstract class AbstractQueryTestCase<QB extends AbstractQueryBuilder<QB>>
|
|||
*/
|
||||
protected static QueryShardContext createShardContext() {
|
||||
QueryShardContext queryCreationContext = new QueryShardContext(index, queryParserService);
|
||||
queryCreationContext.reset();
|
||||
queryCreationContext.parseFieldMatcher(ParseFieldMatcher.EMPTY);
|
||||
return queryCreationContext;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,159 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch 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.index.query;
|
||||
|
||||
import com.carrotsearch.randomizedtesting.generators.RandomPicks;
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.apache.lucene.search.join.ScoreMode;
|
||||
import org.apache.lucene.search.join.ToParentBlockJoinQuery;
|
||||
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
|
||||
import org.elasticsearch.common.ParseFieldMatcher;
|
||||
import org.elasticsearch.common.compress.CompressedXContent;
|
||||
import org.elasticsearch.common.xcontent.*;
|
||||
import org.elasticsearch.index.fielddata.IndexFieldDataService;
|
||||
import org.elasticsearch.index.mapper.MapperService;
|
||||
import org.elasticsearch.index.query.support.QueryInnerHits;
|
||||
import org.elasticsearch.search.fetch.innerhits.InnerHitsBuilder;
|
||||
import org.elasticsearch.search.fetch.innerhits.InnerHitsContext;
|
||||
import org.elasticsearch.search.internal.SearchContext;
|
||||
import org.elasticsearch.search.sort.SortOrder;
|
||||
import org.elasticsearch.test.TestSearchContext;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.instanceOf;
|
||||
|
||||
public class NestedQueryBuilderTests extends AbstractQueryTestCase<NestedQueryBuilder> {
|
||||
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
MapperService mapperService = queryParserService().mapperService;
|
||||
mapperService.merge("nested_doc", new CompressedXContent(PutMappingRequest.buildFromSimplifiedDef("nested_doc",
|
||||
STRING_FIELD_NAME, "type=string",
|
||||
INT_FIELD_NAME, "type=integer",
|
||||
DOUBLE_FIELD_NAME, "type=double",
|
||||
BOOLEAN_FIELD_NAME, "type=boolean",
|
||||
DATE_FIELD_NAME, "type=date",
|
||||
OBJECT_FIELD_NAME, "type=object",
|
||||
"nested1", "type=nested"
|
||||
).string()), false, false);
|
||||
}
|
||||
|
||||
protected void setSearchContext(String[] types) {
|
||||
final MapperService mapperService = queryParserService().mapperService;
|
||||
final IndexFieldDataService fieldData = queryParserService().fieldDataService;
|
||||
TestSearchContext testSearchContext = new TestSearchContext() {
|
||||
private InnerHitsContext context;
|
||||
|
||||
|
||||
@Override
|
||||
public void innerHits(InnerHitsContext innerHitsContext) {
|
||||
context = innerHitsContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InnerHitsContext innerHits() {
|
||||
return context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MapperService mapperService() {
|
||||
return mapperService; // need to build / parse inner hits sort fields
|
||||
}
|
||||
|
||||
@Override
|
||||
public IndexFieldDataService fieldData() {
|
||||
return fieldData; // need to build / parse inner hits sort fields
|
||||
}
|
||||
};
|
||||
testSearchContext.setTypes(types);
|
||||
SearchContext.setCurrent(testSearchContext);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a {@link HasChildQueryBuilder} with random values all over the place
|
||||
*/
|
||||
@Override
|
||||
protected NestedQueryBuilder doCreateTestQueryBuilder() {
|
||||
InnerHitsBuilder.InnerHit innerHit = new InnerHitsBuilder.InnerHit().setSize(100).addSort(STRING_FIELD_NAME, SortOrder.ASC);
|
||||
return new NestedQueryBuilder("nested1", RandomQueryBuilder.createQuery(random()),
|
||||
RandomPicks.randomFrom(random(), ScoreMode.values()),
|
||||
SearchContext.current() == null ? null : new QueryInnerHits("inner_hits_name", innerHit));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doAssertLuceneQuery(NestedQueryBuilder queryBuilder, Query query, QueryShardContext context) throws IOException {
|
||||
QueryBuilder innerQueryBuilder = queryBuilder.query();
|
||||
if (innerQueryBuilder instanceof EmptyQueryBuilder) {
|
||||
assertNull(query);
|
||||
} else {
|
||||
assertThat(query, instanceOf(ToParentBlockJoinQuery.class));
|
||||
ToParentBlockJoinQuery parentBlockJoinQuery = (ToParentBlockJoinQuery) query;
|
||||
//TODO how to assert this?
|
||||
}
|
||||
if (queryBuilder.innerHit() != null) {
|
||||
assertNotNull(SearchContext.current());
|
||||
if (query != null) {
|
||||
assertNotNull(SearchContext.current().innerHits());
|
||||
assertEquals(1, SearchContext.current().innerHits().getInnerHits().size());
|
||||
assertTrue(SearchContext.current().innerHits().getInnerHits().containsKey("inner_hits_name"));
|
||||
InnerHitsContext.BaseInnerHits innerHits = SearchContext.current().innerHits().getInnerHits().get("inner_hits_name");
|
||||
assertEquals(innerHits.size(), 100);
|
||||
assertEquals(innerHits.sort().getSort().length, 1);
|
||||
assertEquals(innerHits.sort().getSort()[0].getField(), STRING_FIELD_NAME);
|
||||
} else {
|
||||
assertNull(SearchContext.current().innerHits());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void testParseDeprecatedFilter() throws IOException {
|
||||
XContentBuilder builder = XContentFactory.jsonBuilder().prettyPrint();
|
||||
builder.startObject();
|
||||
builder.startObject("nested");
|
||||
builder.startObject("filter");
|
||||
builder.startObject("terms").array(STRING_FIELD_NAME, "a", "b").endObject();// deprecated
|
||||
builder.endObject();
|
||||
builder.field("path", "foo.bar");
|
||||
builder.endObject();
|
||||
builder.endObject();
|
||||
|
||||
QueryShardContext shardContext = createShardContext();
|
||||
QueryParseContext context = shardContext.parseContext();
|
||||
XContentParser parser = XContentFactory.xContent(XContentType.JSON).createParser(builder.string());
|
||||
context.reset(parser);
|
||||
context.parseFieldMatcher(ParseFieldMatcher.STRICT);
|
||||
try {
|
||||
context.parseInnerQueryBuilder();
|
||||
fail("filter is deprecated");
|
||||
} catch (IllegalArgumentException ex) {
|
||||
assertEquals("Deprecated field [filter] used, replaced by [query]", ex.getMessage());
|
||||
}
|
||||
|
||||
parser = XContentFactory.xContent(XContentType.JSON).createParser(builder.string());
|
||||
context.reset(parser);
|
||||
NestedQueryBuilder queryBuilder = (NestedQueryBuilder) context.parseInnerQueryBuilder();
|
||||
QueryBuilder query = queryBuilder.query();
|
||||
assertTrue(query instanceof TermsQueryBuilder);
|
||||
TermsQueryBuilder tqb = (TermsQueryBuilder) query;
|
||||
assertEquals(tqb.values(), Arrays.asList("a", "b"));
|
||||
}
|
||||
}
|
|
@ -20,6 +20,7 @@
|
|||
package org.elasticsearch.nested;
|
||||
|
||||
import org.apache.lucene.search.Explanation;
|
||||
import org.apache.lucene.search.join.ScoreMode;
|
||||
import org.elasticsearch.action.admin.cluster.health.ClusterHealthStatus;
|
||||
import org.elasticsearch.action.admin.cluster.stats.ClusterStatsResponse;
|
||||
import org.elasticsearch.action.admin.indices.stats.IndicesStatsResponse;
|
||||
|
@ -311,7 +312,7 @@ public class SimpleNestedIT extends ESIntegTestCase {
|
|||
.execute().actionGet();
|
||||
|
||||
SearchResponse searchResponse = client().prepareSearch("test")
|
||||
.setQuery(nestedQuery("nested1", termQuery("nested1.n_field1", "n_value1")).scoreMode("total"))
|
||||
.setQuery(nestedQuery("nested1", termQuery("nested1.n_field1", "n_value1")).scoreMode(ScoreMode.Total))
|
||||
.setExplain(true)
|
||||
.execute().actionGet();
|
||||
assertNoFailures(searchResponse);
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
*/
|
||||
package org.elasticsearch.percolator;
|
||||
|
||||
import org.apache.lucene.search.join.ScoreMode;
|
||||
import org.elasticsearch.action.ShardOperationFailedException;
|
||||
import org.elasticsearch.action.percolate.MultiPercolateRequestBuilder;
|
||||
import org.elasticsearch.action.percolate.MultiPercolateResponse;
|
||||
|
@ -361,7 +362,7 @@ public class MultiPercolatorIT extends ESIntegTestCase {
|
|||
ensureGreen("nestedindex");
|
||||
|
||||
client().prepareIndex("nestedindex", PercolatorService.TYPE_NAME, "Q").setSource(jsonBuilder().startObject()
|
||||
.field("query", QueryBuilders.nestedQuery("employee", QueryBuilders.matchQuery("employee.name", "virginia potts").operator(Operator.AND)).scoreMode("avg")).endObject()).get();
|
||||
.field("query", QueryBuilders.nestedQuery("employee", QueryBuilders.matchQuery("employee.name", "virginia potts").operator(Operator.AND)).scoreMode(ScoreMode.Avg)).endObject()).get();
|
||||
|
||||
refresh();
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
*/
|
||||
package org.elasticsearch.percolator;
|
||||
|
||||
import org.apache.lucene.search.join.ScoreMode;
|
||||
import org.elasticsearch.action.ShardOperationFailedException;
|
||||
import org.elasticsearch.action.admin.cluster.node.stats.NodeStats;
|
||||
import org.elasticsearch.action.admin.cluster.node.stats.NodesStatsResponse;
|
||||
|
@ -1812,7 +1813,7 @@ public class PercolatorIT extends ESIntegTestCase {
|
|||
ensureGreen("nestedindex");
|
||||
|
||||
client().prepareIndex("nestedindex", PercolatorService.TYPE_NAME, "Q").setSource(jsonBuilder().startObject()
|
||||
.field("query", QueryBuilders.nestedQuery("employee", QueryBuilders.matchQuery("employee.name", "virginia potts").operator(Operator.AND)).scoreMode("avg")).endObject()).get();
|
||||
.field("query", QueryBuilders.nestedQuery("employee", QueryBuilders.matchQuery("employee.name", "virginia potts").operator(Operator.AND)).scoreMode(ScoreMode.Avg)).endObject()).get();
|
||||
|
||||
refresh();
|
||||
|
||||
|
|
Loading…
Reference in New Issue