diff --git a/docs/java-api/query-dsl-queries.asciidoc b/docs/java-api/query-dsl-queries.asciidoc index 92e0982d4e571..db6126183a9e9 100644 --- a/docs/java-api/query-dsl-queries.asciidoc +++ b/docs/java-api/query-dsl-queries.asciidoc @@ -397,28 +397,6 @@ QueryBuilder qb = termsQuery("tags", <1> <2> values <3> how many terms must match at least -[[top-children]] -=== Top Children Query - -See {ref}/query-dsl-top-children-query.html[Top Children Query] - -[source,java] --------------------------------------------------- -QueryBuilder qb = topChildrenQuery( - "blog_tag", <1> - termQuery("tag", "something") <2> - ) - .score("max") <3> - .factor(5) <4> - .incrementalFactor(2); <5> --------------------------------------------------- -<1> field -<2> query -<3> `max`, `sum` or `avg` -<4> how many hits are asked for in the first child query run (defaults to 5) -<5> if not enough parents are found, and there are still more child docs to query, then the child search hits are - expanded by multiplying by the incremental_factor (defaults to 2). - [[wildcard]] === Wildcard Query diff --git a/docs/reference/docs/delete-by-query.asciidoc b/docs/reference/docs/delete-by-query.asciidoc index 06aaf650d1f8a..911624441cb98 100644 --- a/docs/reference/docs/delete-by-query.asciidoc +++ b/docs/reference/docs/delete-by-query.asciidoc @@ -144,4 +144,4 @@ is the same). [[limitations]] === Limitations -The delete by query does not support the following queries and filters: `has_child`, `has_parent` and `top_children`. +The delete by query does not support the following queries and filters: `has_child` and `has_parent`. diff --git a/docs/reference/migration/migrate_2_0.asciidoc b/docs/reference/migration/migrate_2_0.asciidoc index e8f0ebff33ac3..06efc7a59af73 100644 --- a/docs/reference/migration/migrate_2_0.asciidoc +++ b/docs/reference/migration/migrate_2_0.asciidoc @@ -513,3 +513,10 @@ Client client = TransportClient.builder().settings(settings).build(); Log messages are now truncated at 10,000 characters. This can be changed in the `logging.yml` configuration file. + +[float] +=== Removed `top_children` query + +The `top_children` query has been removed in favour of the `has_child` query. The `top_children` query wasn't always faster +than the `has_child` query and the `top_children` query was often inaccurate. The total hits and any aggregations in the +same search request will likely be off if `top_children` was used. \ No newline at end of file diff --git a/docs/reference/query-dsl/has-child-query.asciidoc b/docs/reference/query-dsl/has-child-query.asciidoc index 873a934d711b6..fde4930610492 100644 --- a/docs/reference/query-dsl/has-child-query.asciidoc +++ b/docs/reference/query-dsl/has-child-query.asciidoc @@ -19,11 +19,6 @@ an example: } -------------------------------------------------- -An important difference with the `top_children` query is that this query -is always executed in two iterations whereas the `top_children` query -can be executed in one or more iteration. When using the `has_child` -query the `total_hits` is always correct. - [float] === Scoring capabilities diff --git a/docs/reference/query-dsl/index.asciidoc b/docs/reference/query-dsl/index.asciidoc index 9f102f5348201..026c80f559a04 100644 --- a/docs/reference/query-dsl/index.asciidoc +++ b/docs/reference/query-dsl/index.asciidoc @@ -82,8 +82,6 @@ include::term-query.asciidoc[] include::terms-query.asciidoc[] -include::top-children-query.asciidoc[] - include::wildcard-query.asciidoc[] include::minimum-should-match.asciidoc[] diff --git a/docs/reference/query-dsl/top-children-query.asciidoc b/docs/reference/query-dsl/top-children-query.asciidoc deleted file mode 100644 index 141ec4f799300..0000000000000 --- a/docs/reference/query-dsl/top-children-query.asciidoc +++ /dev/null @@ -1,86 +0,0 @@ -[[query-dsl-top-children-query]] -== Top Children Query - -deprecated[1.6.0, Use the `has_child` query instead] - -The `top_children` query runs the child query with an estimated hits -size, and out of the hit docs, aggregates it into parent docs. If there -aren't enough parent docs matching the requested from/size search -request, then it is run again with a wider (more hits) search. - -The `top_children` also provide scoring capabilities, with the ability -to specify `max`, `sum` or `avg` as the score type. - -One downside of using the `top_children` is that if there are more child -docs matching the required hits when executing the child query, then the -`total_hits` result of the search response will be incorrect. - -How many hits are asked for in the first child query run is controlled -using the `factor` parameter (defaults to `5`). For example, when asking -for 10 parent docs (with `from` set to 0), then the child query will -execute with 50 hits expected. If not enough parents are found (in our -example 10), and there are still more child docs to query, then the -child search hits are expanded by multiplying by the -`incremental_factor` (defaults to `2`). - -The required parameters are the `query` and `type` (the child type to -execute the query on). Here is an example with all different parameters, -including the default values: - -[source,js] --------------------------------------------------- -{ - "top_children" : { - "type": "blog_tag", - "query" : { - "term" : { - "tag" : "something" - } - }, - "score" : "max", - "factor" : 5, - "incremental_factor" : 2 - } -} --------------------------------------------------- - -[float] -=== Scope - -A `_scope` can be defined on the query allowing to run aggregations on the -same scope name that will work against the child documents. For example: - -[source,js] --------------------------------------------------- -{ - "top_children" : { - "_scope" : "my_scope", - "type": "blog_tag", - "query" : { - "term" : { - "tag" : "something" - } - } - } -} --------------------------------------------------- - -[float] -=== Memory Considerations - -In order to support parent-child joins, all of the (string) parent IDs -must be resident in memory (in the <>. -Additionally, every child document is mapped to its parent using a long -value (approximately). It is advisable to keep the string parent ID short -in order to reduce memory usage. - -You can check how much memory is being used by the ID cache using the -<> or <> -APIS, eg: - -[source,js] --------------------------------------------------- -curl -XGET "http://localhost:9200/_stats/id_cache?pretty&human" --------------------------------------------------- - - diff --git a/docs/reference/search/percolate.asciidoc b/docs/reference/search/percolate.asciidoc index f782fc718851b..26eea8a0ba057 100644 --- a/docs/reference/search/percolate.asciidoc +++ b/docs/reference/search/percolate.asciidoc @@ -491,7 +491,7 @@ the time the percolate API needs to run can be decreased. === Important Notes Because the percolator API is processing one document at a time, it doesn't support queries and filters that run -against child documents such as `has_child`, `has_parent` and `top_children`. +against child documents such as `has_child` and `has_parent`. The `wildcard` and `regexp` query natively use a lot of memory and because the percolator keeps the queries into memory this can easily take up the available memory in the heap space. If possible try to use a `prefix` query or ngramming to diff --git a/src/main/java/org/elasticsearch/index/query/QueryBuilders.java b/src/main/java/org/elasticsearch/index/query/QueryBuilders.java index 5cdd638f6870a..2cfc41769abf6 100644 --- a/src/main/java/org/elasticsearch/index/query/QueryBuilders.java +++ b/src/main/java/org/elasticsearch/index/query/QueryBuilders.java @@ -423,18 +423,6 @@ public static MoreLikeThisQueryBuilder moreLikeThisQuery() { return new MoreLikeThisQueryBuilder(); } - /** - * Constructs a new scoring child query, with the child type and the query to run on the child documents. The - * results of this query are the parent docs that those child docs matched. - * - * @param type The child type. - * @param query The query. - */ - @Deprecated - public static TopChildrenQueryBuilder topChildrenQuery(String type, QueryBuilder query) { - return new TopChildrenQueryBuilder(type, query); - } - /** * Constructs a new NON scoring child query, with the child type and the query to run on the child documents. The * results of this query are the parent docs that those child docs matched. diff --git a/src/main/java/org/elasticsearch/index/query/TopChildrenQueryBuilder.java b/src/main/java/org/elasticsearch/index/query/TopChildrenQueryBuilder.java deleted file mode 100644 index 011f681722769..0000000000000 --- a/src/main/java/org/elasticsearch/index/query/TopChildrenQueryBuilder.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * 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 org.elasticsearch.common.xcontent.XContentBuilder; - -import java.io.IOException; - -/** - * - */ -@Deprecated -public class TopChildrenQueryBuilder extends BaseQueryBuilder implements BoostableQueryBuilder { - - private final QueryBuilder queryBuilder; - - private String childType; - - private String score; - - private float boost = 1.0f; - - private int factor = -1; - - private int incrementalFactor = -1; - - private String queryName; - - public TopChildrenQueryBuilder(String type, QueryBuilder queryBuilder) { - this.childType = type; - this.queryBuilder = queryBuilder; - } - - /** - * How to compute the score. Possible values are: max, sum, or avg. Defaults - * to max. - */ - public TopChildrenQueryBuilder score(String score) { - this.score = score; - return this; - } - - /** - * Controls the multiplication factor of the initial hits required from the child query over the main query request. - * Defaults to 5. - */ - public TopChildrenQueryBuilder factor(int factor) { - this.factor = factor; - return this; - } - - /** - * Sets the incremental factor when the query needs to be re-run in order to fetch more results. Defaults to 2. - */ - public TopChildrenQueryBuilder incrementalFactor(int incrementalFactor) { - this.incrementalFactor = incrementalFactor; - return this; - } - - /** - * Sets the boost for this query. Documents matching this query will (in addition to the normal - * weightings) have their score multiplied by the boost provided. - */ - @Override - public TopChildrenQueryBuilder boost(float boost) { - this.boost = boost; - return this; - } - - /** - * Sets the query name for the filter that can be used when searching for matched_filters per hit. - */ - public TopChildrenQueryBuilder queryName(String queryName) { - this.queryName = queryName; - return this; - } - - @Override - protected void doXContent(XContentBuilder builder, Params params) throws IOException { - builder.startObject(TopChildrenQueryParser.NAME); - builder.field("query"); - queryBuilder.toXContent(builder, params); - builder.field("type", childType); - if (score != null) { - builder.field("score", score); - } - if (boost != -1) { - builder.field("boost", boost); - } - if (factor != -1) { - builder.field("factor", factor); - } - if (incrementalFactor != -1) { - builder.field("incremental_factor", incrementalFactor); - } - if (queryName != null) { - builder.field("_name", queryName); - } - builder.endObject(); - } -} diff --git a/src/main/java/org/elasticsearch/index/query/TopChildrenQueryParser.java b/src/main/java/org/elasticsearch/index/query/TopChildrenQueryParser.java deleted file mode 100644 index fe1e13fccebf6..0000000000000 --- a/src/main/java/org/elasticsearch/index/query/TopChildrenQueryParser.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * 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 org.apache.lucene.search.Query; -import org.apache.lucene.search.join.BitDocIdSetFilter; -import org.elasticsearch.common.Strings; -import org.elasticsearch.common.inject.Inject; -import org.elasticsearch.common.lucene.search.Queries; -import org.elasticsearch.common.xcontent.XContentParser; -import org.elasticsearch.index.fielddata.plain.ParentChildIndexFieldData; -import org.elasticsearch.index.mapper.DocumentMapper; -import org.elasticsearch.index.mapper.internal.ParentFieldMapper; -import org.elasticsearch.index.query.support.XContentStructure; -import org.elasticsearch.index.search.child.ScoreType; -import org.elasticsearch.index.search.child.TopChildrenQuery; - -import java.io.IOException; - -/** - * - */ -@Deprecated -public class TopChildrenQueryParser implements QueryParser { - - public static final String NAME = "top_children"; - - @Inject - public TopChildrenQueryParser() { - } - - @Override - public String[] names() { - return new String[]{NAME, Strings.toCamelCase(NAME)}; - } - - @Override - public Query parse(QueryParseContext parseContext) throws IOException, QueryParsingException { - XContentParser parser = parseContext.parser(); - - boolean queryFound = false; - float boost = 1.0f; - String childType = null; - ScoreType scoreType = ScoreType.MAX; - int factor = 5; - int incrementalFactor = 2; - String queryName = null; - - String currentFieldName = null; - XContentParser.Token token; - XContentStructure.InnerQuery iq = null; - while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { - if (token == XContentParser.Token.FIELD_NAME) { - currentFieldName = parser.currentName(); - } else if (token == XContentParser.Token.START_OBJECT) { - // Usually, the query would be parsed here, but the child - // type may not have been extracted yet, so use the - // XContentStructure. facade to parse if available, - // or delay parsing if not. - if ("query".equals(currentFieldName)) { - iq = new XContentStructure.InnerQuery(parseContext, childType == null ? null : new String[] {childType}); - queryFound = true; - } else { - throw new QueryParsingException(parseContext, "[top_children] query does not support [" + currentFieldName + "]"); - } - } else if (token.isValue()) { - if ("type".equals(currentFieldName)) { - childType = parser.text(); - } else if ("score".equals(currentFieldName)) { - scoreType = ScoreType.fromString(parser.text()); - } else if ("score_mode".equals(currentFieldName) || "scoreMode".equals(currentFieldName)) { - scoreType = ScoreType.fromString(parser.text()); - } else if ("boost".equals(currentFieldName)) { - boost = parser.floatValue(); - } else if ("factor".equals(currentFieldName)) { - factor = parser.intValue(); - } else if ("incremental_factor".equals(currentFieldName) || "incrementalFactor".equals(currentFieldName)) { - incrementalFactor = parser.intValue(); - } else if ("_name".equals(currentFieldName)) { - queryName = parser.text(); - } else { - throw new QueryParsingException(parseContext, "[top_children] query does not support [" + currentFieldName + "]"); - } - } - } - if (!queryFound) { - throw new QueryParsingException(parseContext, "[top_children] requires 'query' field"); - } - if (childType == null) { - throw new QueryParsingException(parseContext, "[top_children] requires 'type' field"); - } - - Query innerQuery = iq.asQuery(childType); - - if (innerQuery == null) { - return null; - } - - DocumentMapper childDocMapper = parseContext.mapperService().documentMapper(childType); - if (childDocMapper == null) { - throw new QueryParsingException(parseContext, "No mapping for for type [" + childType + "]"); - } - ParentFieldMapper parentFieldMapper = childDocMapper.parentFieldMapper(); - if (!parentFieldMapper.active()) { - throw new QueryParsingException(parseContext, "Type [" + childType + "] does not have parent mapping"); - } - String parentType = childDocMapper.parentFieldMapper().type(); - - BitDocIdSetFilter nonNestedDocsFilter = null; - if (childDocMapper.hasNestedObjects()) { - nonNestedDocsFilter = parseContext.bitsetFilter(Queries.newNonNestedFilter()); - } - - innerQuery.setBoost(boost); - // wrap the query with type query - innerQuery = Queries.filtered(innerQuery, childDocMapper.typeFilter()); - ParentChildIndexFieldData parentChildIndexFieldData = parseContext.getForField(parentFieldMapper); - TopChildrenQuery query = new TopChildrenQuery(parentChildIndexFieldData, innerQuery, childType, parentType, scoreType, factor, incrementalFactor, nonNestedDocsFilter); - if (queryName != null) { - parseContext.addNamedQuery(queryName, query); - } - return query; - } -} diff --git a/src/main/java/org/elasticsearch/index/search/child/TopChildrenQuery.java b/src/main/java/org/elasticsearch/index/search/child/TopChildrenQuery.java deleted file mode 100644 index a211621f69a03..0000000000000 --- a/src/main/java/org/elasticsearch/index/search/child/TopChildrenQuery.java +++ /dev/null @@ -1,406 +0,0 @@ -/* - * 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.search.child; - -import com.carrotsearch.hppc.IntObjectOpenHashMap; -import com.carrotsearch.hppc.ObjectObjectOpenHashMap; - -import org.apache.lucene.index.*; -import org.apache.lucene.search.*; -import org.apache.lucene.util.*; -import org.elasticsearch.ElasticsearchException; -import org.elasticsearch.common.lease.Releasable; -import org.elasticsearch.common.lucene.IndexCacheableQuery; -import org.elasticsearch.common.lucene.search.EmptyScorer; -import org.apache.lucene.search.join.BitDocIdSetFilter; -import org.elasticsearch.index.fielddata.IndexParentChildFieldData; -import org.elasticsearch.index.mapper.Uid; -import org.elasticsearch.index.mapper.internal.UidFieldMapper; -import org.elasticsearch.search.internal.SearchContext; -import org.elasticsearch.search.internal.SearchContext.Lifetime; - -import java.io.IOException; -import java.util.Arrays; -import java.util.Comparator; -import java.util.Set; - -/** - * A query that evaluates the top matching child documents (based on the score) in order to determine what - * parent documents to return. This query tries to find just enough child documents to return the the requested - * number of parent documents (or less if no other child document can be found). - *

- * This query executes several internal searches. In the first round it tries to find ((request offset + requested size) * factor) - * child documents. The resulting child documents are mapped into their parent documents including the aggragted child scores. - * If not enough parent documents could be resolved then a subsequent round is executed, requesting previous requested - * documents times incremental_factor. This logic repeats until enough parent documents are resolved or until no more - * child documents are available. - *

- * This query is most of the times faster than the {@link ChildrenQuery}. Usually enough parent documents can be returned - * in the first child document query round. - */ -@Deprecated -public class TopChildrenQuery extends IndexCacheableQuery { - - private static final ParentDocComparator PARENT_DOC_COMP = new ParentDocComparator(); - - private final IndexParentChildFieldData parentChildIndexFieldData; - private final String parentType; - private final String childType; - private final ScoreType scoreType; - private final int factor; - private final int incrementalFactor; - private Query childQuery; - private final BitDocIdSetFilter nonNestedDocsFilter; - - // Note, the query is expected to already be filtered to only child type docs - public TopChildrenQuery(IndexParentChildFieldData parentChildIndexFieldData, Query childQuery, String childType, String parentType, ScoreType scoreType, int factor, int incrementalFactor, BitDocIdSetFilter nonNestedDocsFilter) { - this.parentChildIndexFieldData = parentChildIndexFieldData; - this.childQuery = childQuery; - this.childType = childType; - this.parentType = parentType; - this.scoreType = scoreType; - this.factor = factor; - this.incrementalFactor = incrementalFactor; - this.nonNestedDocsFilter = nonNestedDocsFilter; - } - - @Override - public Query rewrite(IndexReader reader) throws IOException { - Query childRewritten = childQuery.rewrite(reader); - if (childRewritten != childQuery) { - Query rewritten = new TopChildrenQuery(parentChildIndexFieldData, childRewritten, childType, parentType, scoreType, factor, incrementalFactor, nonNestedDocsFilter); - rewritten.setBoost(getBoost()); - return rewritten; - } - return super.rewrite(reader); - } - - @Override - public Weight doCreateWeight(IndexSearcher searcher, boolean needsScores) throws IOException { - ObjectObjectOpenHashMap parentDocs = new ObjectObjectOpenHashMap<>(); - SearchContext searchContext = SearchContext.current(); - - int parentHitsResolved; - int requestedDocs = (searchContext.from() + searchContext.size()); - if (requestedDocs <= 0) { - requestedDocs = 1; - } - int numChildDocs = requestedDocs * factor; - - IndexSearcher indexSearcher = new IndexSearcher(searcher.getIndexReader()); - indexSearcher.setSimilarity(searcher.getSimilarity()); - indexSearcher.setQueryCache(null); - while (true) { - parentDocs.clear(); - TopDocs topChildDocs = indexSearcher.search(childQuery, numChildDocs); - try { - parentHitsResolved = resolveParentDocuments(topChildDocs, searchContext, parentDocs); - } catch (Exception e) { - throw new IOException(e); - } - - // check if we found enough docs, if so, break - if (parentHitsResolved >= requestedDocs) { - break; - } - // if we did not find enough docs, check if it make sense to search further - if (topChildDocs.totalHits <= numChildDocs) { - break; - } - // if not, update numDocs, and search again - numChildDocs *= incrementalFactor; - if (numChildDocs > topChildDocs.totalHits) { - numChildDocs = topChildDocs.totalHits; - } - } - - ParentWeight parentWeight = new ParentWeight(this, childQuery.createWeight(searcher, needsScores), parentDocs); - searchContext.addReleasable(parentWeight, Lifetime.COLLECTION); - return parentWeight; - } - - int resolveParentDocuments(TopDocs topDocs, SearchContext context, ObjectObjectOpenHashMap parentDocs) throws Exception { - int parentHitsResolved = 0; - ObjectObjectOpenHashMap> parentDocsPerReader = new ObjectObjectOpenHashMap<>(context.searcher().getIndexReader().leaves().size()); - child_hits: for (ScoreDoc scoreDoc : topDocs.scoreDocs) { - int readerIndex = ReaderUtil.subIndex(scoreDoc.doc, context.searcher().getIndexReader().leaves()); - LeafReaderContext subContext = context.searcher().getIndexReader().leaves().get(readerIndex); - SortedDocValues parentValues = parentChildIndexFieldData.load(subContext).getOrdinalsValues(parentType); - int subDoc = scoreDoc.doc - subContext.docBase; - - // find the parent id - BytesRef parentId = parentValues.get(subDoc); - if (parentId == null) { - // no parent found - continue; - } - // now go over and find the parent doc Id and reader tuple - for (LeafReaderContext atomicReaderContext : context.searcher().getIndexReader().leaves()) { - LeafReader indexReader = atomicReaderContext.reader(); - BitSet nonNestedDocs = null; - if (nonNestedDocsFilter != null) { - BitDocIdSet nonNestedDocIdSet = nonNestedDocsFilter.getDocIdSet(atomicReaderContext); - if (nonNestedDocIdSet != null) { - nonNestedDocs = nonNestedDocIdSet.bits(); - } - } - - Terms terms = indexReader.terms(UidFieldMapper.NAME); - if (terms == null) { - continue; - } - TermsEnum termsEnum = terms.iterator(); - if (!termsEnum.seekExact(Uid.createUidAsBytes(parentType, parentId))) { - continue; - } - PostingsEnum docsEnum = termsEnum.postings(indexReader.getLiveDocs(), null, PostingsEnum.NONE); - int parentDocId = docsEnum.nextDoc(); - if (nonNestedDocs != null && !nonNestedDocs.get(parentDocId)) { - parentDocId = nonNestedDocs.nextSetBit(parentDocId); - } - if (parentDocId != DocIdSetIterator.NO_MORE_DOCS) { - // we found a match, add it and break - IntObjectOpenHashMap readerParentDocs = parentDocsPerReader.get(indexReader.getCoreCacheKey()); - if (readerParentDocs == null) { - //The number of docs in the reader and in the query both upper bound the size of parentDocsPerReader - int mapSize = Math.min(indexReader.maxDoc(), context.from() + context.size()); - readerParentDocs = new IntObjectOpenHashMap<>(mapSize); - parentDocsPerReader.put(indexReader.getCoreCacheKey(), readerParentDocs); - } - ParentDoc parentDoc = readerParentDocs.get(parentDocId); - if (parentDoc == null) { - parentHitsResolved++; // we have a hit on a parent - parentDoc = new ParentDoc(); - parentDoc.docId = parentDocId; - parentDoc.count = 1; - parentDoc.maxScore = scoreDoc.score; - parentDoc.minScore = scoreDoc.score; - parentDoc.sumScores = scoreDoc.score; - readerParentDocs.put(parentDocId, parentDoc); - } else { - parentDoc.count++; - parentDoc.sumScores += scoreDoc.score; - if (scoreDoc.score < parentDoc.minScore) { - parentDoc.minScore = scoreDoc.score; - } - if (scoreDoc.score > parentDoc.maxScore) { - parentDoc.maxScore = scoreDoc.score; - } - } - continue child_hits; - } - } - } - boolean[] states = parentDocsPerReader.allocated; - Object[] keys = parentDocsPerReader.keys; - Object[] values = parentDocsPerReader.values; - for (int i = 0; i < states.length; i++) { - if (states[i]) { - IntObjectOpenHashMap value = (IntObjectOpenHashMap) values[i]; - ParentDoc[] _parentDocs = value.values().toArray(ParentDoc.class); - Arrays.sort(_parentDocs, PARENT_DOC_COMP); - parentDocs.put(keys[i], _parentDocs); - } - } - return parentHitsResolved; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (super.equals(obj) == false) { - return false; - } - - TopChildrenQuery that = (TopChildrenQuery) obj; - if (!childQuery.equals(that.childQuery)) { - return false; - } - if (!childType.equals(that.childType)) { - return false; - } - if (incrementalFactor != that.incrementalFactor) { - return false; - } - return true; - } - - @Override - public int hashCode() { - int result = super.hashCode(); - result = 31 * result + childQuery.hashCode(); - result = 31 * result + parentType.hashCode(); - result = 31 * result + incrementalFactor; - return result; - } - - @Override - public String toString(String field) { - StringBuilder sb = new StringBuilder(); - sb.append("score_child[").append(childType).append("/").append(parentType).append("](").append(childQuery.toString(field)).append(')'); - sb.append(ToStringUtils.boost(getBoost())); - return sb.toString(); - } - - private class ParentWeight extends Weight implements Releasable { - - private final Weight queryWeight; - private final ObjectObjectOpenHashMap parentDocs; - - public ParentWeight(Query query, Weight queryWeight, ObjectObjectOpenHashMap parentDocs) throws IOException { - super(query); - this.queryWeight = queryWeight; - this.parentDocs = parentDocs; - } - - @Override - public void extractTerms(Set terms) { - } - - @Override - public float getValueForNormalization() throws IOException { - float sum = queryWeight.getValueForNormalization(); - sum *= getBoost() * getBoost(); - return sum; - } - - @Override - public void normalize(float norm, float topLevelBoost) { - // Nothing to normalize - } - - @Override - public void close() { - } - - @Override - public Scorer scorer(LeafReaderContext context, Bits acceptDocs) throws IOException { - ParentDoc[] readerParentDocs = parentDocs.get(context.reader().getCoreCacheKey()); - // We ignore the needsScores parameter here because there isn't really anything that we - // can improve by ignoring scores. Actually this query does not really make sense - // with needsScores=false... - if (readerParentDocs != null) { - if (scoreType == ScoreType.MIN) { - return new ParentScorer(this, readerParentDocs) { - @Override - public float score() throws IOException { - assert doc.docId >= 0 && doc.docId != NO_MORE_DOCS; - return doc.minScore; - } - }; - } else if (scoreType == ScoreType.MAX) { - return new ParentScorer(this, readerParentDocs) { - @Override - public float score() throws IOException { - assert doc.docId >= 0 && doc.docId != NO_MORE_DOCS; - return doc.maxScore; - } - }; - } else if (scoreType == ScoreType.AVG) { - return new ParentScorer(this, readerParentDocs) { - @Override - public float score() throws IOException { - assert doc.docId >= 0 && doc.docId != NO_MORE_DOCS; - return doc.sumScores / doc.count; - } - }; - } else if (scoreType == ScoreType.SUM) { - return new ParentScorer(this, readerParentDocs) { - @Override - public float score() throws IOException { - assert doc.docId >= 0 && doc.docId != NO_MORE_DOCS; - return doc.sumScores; - } - - }; - } - throw new IllegalStateException("No support for score type [" + scoreType + "]"); - } - return new EmptyScorer(this); - } - - @Override - public Explanation explain(LeafReaderContext context, int doc) throws IOException { - return Explanation.match(getBoost(), "not implemented yet..."); - } - } - - private static abstract class ParentScorer extends Scorer { - - private final ParentDoc spare = new ParentDoc(); - protected final ParentDoc[] docs; - protected ParentDoc doc = spare; - private int index = -1; - - ParentScorer(ParentWeight weight, ParentDoc[] docs) throws IOException { - super(weight); - this.docs = docs; - spare.docId = -1; - spare.count = -1; - } - - @Override - public final int docID() { - return doc.docId; - } - - @Override - public final int advance(int target) throws IOException { - return slowAdvance(target); - } - - @Override - public final int nextDoc() throws IOException { - if (++index >= docs.length) { - doc = spare; - doc.count = 0; - return (doc.docId = NO_MORE_DOCS); - } - return (doc = docs[index]).docId; - } - - @Override - public final int freq() throws IOException { - return doc.count; // The number of matches in the child doc, which is propagated to parent - } - - @Override - public final long cost() { - return docs.length; - } - } - - private static class ParentDocComparator implements Comparator { - @Override - public int compare(ParentDoc o1, ParentDoc o2) { - return o1.docId - o2.docId; - } - } - - private static class ParentDoc { - public int docId; - public int count; - public float minScore = Float.NaN; - public float maxScore = Float.NaN; - public float sumScores = 0; - } - -} diff --git a/src/main/java/org/elasticsearch/indices/query/IndicesQueriesModule.java b/src/main/java/org/elasticsearch/indices/query/IndicesQueriesModule.java index e911b25aba755..8e4ff94d87df6 100644 --- a/src/main/java/org/elasticsearch/indices/query/IndicesQueriesModule.java +++ b/src/main/java/org/elasticsearch/indices/query/IndicesQueriesModule.java @@ -59,7 +59,6 @@ protected void configure() { qpBinders.addBinding().to(NestedQueryParser.class).asEagerSingleton(); qpBinders.addBinding().to(HasChildQueryParser.class).asEagerSingleton(); qpBinders.addBinding().to(HasParentQueryParser.class).asEagerSingleton(); - qpBinders.addBinding().to(TopChildrenQueryParser.class).asEagerSingleton(); qpBinders.addBinding().to(DisMaxQueryParser.class).asEagerSingleton(); qpBinders.addBinding().to(IdsQueryParser.class).asEagerSingleton(); qpBinders.addBinding().to(MatchAllQueryParser.class).asEagerSingleton(); diff --git a/src/test/java/org/elasticsearch/benchmark/search/child/ChildSearchBenchmark.java b/src/test/java/org/elasticsearch/benchmark/search/child/ChildSearchBenchmark.java index b9f400d886672..e930c2cf3280d 100644 --- a/src/test/java/org/elasticsearch/benchmark/search/child/ChildSearchBenchmark.java +++ b/src/test/java/org/elasticsearch/benchmark/search/child/ChildSearchBenchmark.java @@ -42,7 +42,6 @@ import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery; import static org.elasticsearch.index.query.QueryBuilders.matchQuery; import static org.elasticsearch.index.query.QueryBuilders.termQuery; -import static org.elasticsearch.index.query.QueryBuilders.topChildrenQuery; import static org.elasticsearch.node.NodeBuilder.nodeBuilder; /** @@ -257,37 +256,6 @@ public static void main(String[] args) throws Exception { totalQueryTime += searchResponse.getTookInMillis(); } System.out.println("--> has_parent filter with match_all parent query, Query Avg: " + (totalQueryTime / QUERY_COUNT) + "ms"); - System.out.println("--> Running top_children query"); - // run parent child score query - for (int j = 0; j < QUERY_WARMUP; j++) { - client.prepareSearch(indexName).setQuery(topChildrenQuery("child", termQuery("field2", parentChildIndexGenerator.getQueryValue()))).execute().actionGet(); - } - - totalQueryTime = 0; - for (int j = 0; j < QUERY_COUNT; j++) { - SearchResponse searchResponse = client.prepareSearch(indexName).setQuery(topChildrenQuery("child", termQuery("field2", parentChildIndexGenerator.getQueryValue()))).execute().actionGet(); - if (j % 10 == 0) { - System.out.println("--> hits [" + j + "], got [" + searchResponse.getHits().totalHits() + "]"); - } - totalQueryTime += searchResponse.getTookInMillis(); - } - System.out.println("--> top_children Query Avg: " + (totalQueryTime / QUERY_COUNT) + "ms"); - - System.out.println("--> Running top_children query, with match_all as child query"); - // run parent child score query - for (int j = 0; j < QUERY_WARMUP; j++) { - client.prepareSearch(indexName).setQuery(topChildrenQuery("child", matchAllQuery())).execute().actionGet(); - } - - totalQueryTime = 0; - for (int j = 0; j < QUERY_COUNT; j++) { - SearchResponse searchResponse = client.prepareSearch(indexName).setQuery(topChildrenQuery("child", matchAllQuery())).execute().actionGet(); - if (j % 10 == 0) { - System.out.println("--> hits [" + j + "], got [" + searchResponse.getHits().totalHits() + "]"); - } - totalQueryTime += searchResponse.getTookInMillis(); - } - System.out.println("--> top_children, with match_all Query Avg: " + (totalQueryTime / QUERY_COUNT) + "ms"); statsResponse = client.admin().cluster().prepareNodesStats() .setJvm(true).setIndices(true).execute().actionGet(); diff --git a/src/test/java/org/elasticsearch/index/search/child/TopChildrenQueryTests.java b/src/test/java/org/elasticsearch/index/search/child/TopChildrenQueryTests.java deleted file mode 100644 index 41750cff10b84..0000000000000 --- a/src/test/java/org/elasticsearch/index/search/child/TopChildrenQueryTests.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * 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.search.child; - -import org.apache.lucene.index.Term; -import org.apache.lucene.search.Query; -import org.apache.lucene.search.QueryUtils; -import org.apache.lucene.search.TermQuery; -import org.elasticsearch.common.lease.Releasables; -import org.elasticsearch.common.lucene.search.Queries; -import org.elasticsearch.index.fielddata.plain.ParentChildIndexFieldData; -import org.elasticsearch.index.mapper.internal.ParentFieldMapper; -import org.elasticsearch.search.internal.SearchContext; -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; - -import java.io.IOException; - -/** - */ -public class TopChildrenQueryTests extends AbstractChildTests { - - @BeforeClass - public static void before() throws IOException { - SearchContext.setCurrent(ChildrenConstantScoreQueryTests.createSearchContext("test", "parent", "child")); - } - - @AfterClass - public static void after() throws IOException { - SearchContext current = SearchContext.current(); - SearchContext.removeCurrent(); - Releasables.close(current); - } - - @Test - public void testBasicQuerySanities() { - Query childQuery = new TermQuery(new Term("field", "value")); - ScoreType scoreType = ScoreType.values()[random().nextInt(ScoreType.values().length)]; - ParentFieldMapper parentFieldMapper = SearchContext.current().mapperService().documentMapper("child").parentFieldMapper(); - ParentChildIndexFieldData parentChildIndexFieldData = SearchContext.current().fieldData().getForField(parentFieldMapper); - Query query = new TopChildrenQuery(parentChildIndexFieldData, childQuery, "child", "parent", scoreType, 1, 1, wrapWithBitSetFilter(Queries.newNonNestedFilter())); - QueryUtils.check(query); - } - -} diff --git a/src/test/java/org/elasticsearch/search/child/SimpleChildQuerySearchTests.java b/src/test/java/org/elasticsearch/search/child/SimpleChildQuerySearchTests.java index 4e006683fdfd3..778c5d6c05bfa 100644 --- a/src/test/java/org/elasticsearch/search/child/SimpleChildQuerySearchTests.java +++ b/src/test/java/org/elasticsearch/search/child/SimpleChildQuerySearchTests.java @@ -85,7 +85,6 @@ import static org.elasticsearch.index.query.QueryBuilders.queryStringQuery; import static org.elasticsearch.index.query.QueryBuilders.termQuery; import static org.elasticsearch.index.query.QueryBuilders.termsQuery; -import static org.elasticsearch.index.query.QueryBuilders.topChildrenQuery; import static org.elasticsearch.index.query.functionscore.ScoreFunctionBuilders.factorFunction; import static org.elasticsearch.index.query.functionscore.ScoreFunctionBuilders.scriptFunction; import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked; @@ -253,23 +252,6 @@ public void simpleChildQuery() throws Exception { assertThat(searchResponse.getHits().getAt(1).id(), anyOf(equalTo("c1"), equalTo("c2"))); assertThat(searchResponse.getHits().getAt(1).field("_parent").value().toString(), equalTo("p1")); - // TOP CHILDREN QUERY - searchResponse = client().prepareSearch("test").setQuery(topChildrenQuery("child", termQuery("c_field", "yellow"))).execute() - .actionGet(); - assertHitCount(searchResponse, 1l); - assertThat(searchResponse.getHits().getAt(0).id(), equalTo("p1")); - - searchResponse = client().prepareSearch("test").setQuery(topChildrenQuery("child", termQuery("c_field", "blue"))) - .get(); - assertHitCount(searchResponse, 1l); - assertThat(searchResponse.getHits().getAt(0).id(), equalTo("p2")); - - searchResponse = client().prepareSearch("test").setQuery(topChildrenQuery("child", termQuery("c_field", "red"))).execute() - .actionGet(); - assertHitCount(searchResponse, 2l); - assertThat(searchResponse.getHits().getAt(0).id(), anyOf(equalTo("p2"), equalTo("p1"))); - assertThat(searchResponse.getHits().getAt(1).id(), anyOf(equalTo("p2"), equalTo("p1"))); - // HAS CHILD searchResponse = client().prepareSearch("test").setQuery(randomHasChild("child", "c_field", "yellow")) .get(); @@ -414,10 +396,6 @@ public void testCachingBug_withFqueryFilter() throws Exception { for (int i = 1; i <= 10; i++) { logger.info("Round {}", i); SearchResponse searchResponse = client().prepareSearch("test") - .setQuery(constantScoreQuery(topChildrenQuery("child", matchAllQuery()))).execute() - .actionGet(); - assertNoFailures(searchResponse); - searchResponse = client().prepareSearch("test") .setQuery(constantScoreQuery(hasChildQuery("child", matchAllQuery()).scoreType("max"))) .get(); assertNoFailures(searchResponse); @@ -500,31 +478,9 @@ public void simpleChildQueryWithFlush() throws Exception { client().admin().indices().prepareFlush().get(); refresh(); - // TOP CHILDREN QUERY - - SearchResponse searchResponse = client().prepareSearch("test").setQuery(topChildrenQuery("child", termQuery("c_field", "yellow"))) - .get(); - assertNoFailures(searchResponse); - assertNoFailures(searchResponse); - assertThat(searchResponse.getHits().totalHits(), equalTo(1l)); - assertThat(searchResponse.getHits().getAt(0).id(), equalTo("p1")); - - searchResponse = client().prepareSearch("test").setQuery(topChildrenQuery("child", termQuery("c_field", "blue"))).execute() - .actionGet(); - assertNoFailures(searchResponse); - assertThat(searchResponse.getHits().totalHits(), equalTo(1l)); - assertThat(searchResponse.getHits().getAt(0).id(), equalTo("p2")); - - searchResponse = client().prepareSearch("test").setQuery(topChildrenQuery("child", termQuery("c_field", "red"))).execute() - .actionGet(); - assertNoFailures(searchResponse); - assertThat(searchResponse.getHits().totalHits(), equalTo(2l)); - assertThat(searchResponse.getHits().getAt(0).id(), anyOf(equalTo("p2"), equalTo("p1"))); - assertThat(searchResponse.getHits().getAt(1).id(), anyOf(equalTo("p2"), equalTo("p1"))); - // HAS CHILD QUERY - searchResponse = client().prepareSearch("test").setQuery(hasChildQuery("child", termQuery("c_field", "yellow"))).execute() + SearchResponse searchResponse = client().prepareSearch("test").setQuery(hasChildQuery("child", termQuery("c_field", "yellow"))).execute() .actionGet(); assertNoFailures(searchResponse); assertThat(searchResponse.getHits().totalHits(), equalTo(1l)); @@ -583,7 +539,7 @@ public void testScopedFacet() throws Exception { SearchResponse searchResponse = client() .prepareSearch("test") - .setQuery(topChildrenQuery("child", boolQuery().should(termQuery("c_field", "red")).should(termQuery("c_field", "yellow")))) + .setQuery(hasChildQuery("child", boolQuery().should(termQuery("c_field", "red")).should(termQuery("c_field", "yellow")))) .addAggregation(AggregationBuilders.global("global").subAggregation( AggregationBuilders.filter("filter").filter(boolQuery().should(termQuery("c_field", "red")).should(termQuery("c_field", "yellow"))).subAggregation( AggregationBuilders.terms("facet1").field("c_field")))).get(); @@ -618,16 +574,7 @@ public void testDeletedParent() throws Exception { refresh(); - // TOP CHILDREN QUERY - - SearchResponse searchResponse = client().prepareSearch("test").setQuery(topChildrenQuery("child", termQuery("c_field", "yellow"))) - .get(); - assertNoFailures(searchResponse); - assertThat(searchResponse.getHits().totalHits(), equalTo(1l)); - assertThat(searchResponse.getHits().getAt(0).id(), equalTo("p1")); - assertThat(searchResponse.getHits().getAt(0).sourceAsString(), containsString("\"p_value1\"")); - - searchResponse = client().prepareSearch("test") + SearchResponse searchResponse = client().prepareSearch("test") .setQuery(constantScoreQuery(hasChildQuery("child", termQuery("c_field", "yellow")))).get(); assertNoFailures(searchResponse); assertThat(searchResponse.getHits().totalHits(), equalTo(1l)); @@ -639,13 +586,6 @@ public void testDeletedParent() throws Exception { client().prepareIndex("test", "parent", "p1").setSource("p_field", "p_value1_updated").get(); client().admin().indices().prepareRefresh().get(); - searchResponse = client().prepareSearch("test").setQuery(topChildrenQuery("child", termQuery("c_field", "yellow"))).execute() - .actionGet(); - assertNoFailures(searchResponse); - assertThat(searchResponse.getHits().totalHits(), equalTo(1l)); - assertThat(searchResponse.getHits().getAt(0).id(), equalTo("p1")); - assertThat(searchResponse.getHits().getAt(0).sourceAsString(), containsString("\"p_value1_updated\"")); - searchResponse = client().prepareSearch("test") .setQuery(constantScoreQuery(hasChildQuery("child", termQuery("c_field", "yellow")))).get(); assertNoFailures(searchResponse); @@ -679,69 +619,6 @@ public void testDfsSearchType() throws Exception { .setQuery(boolQuery().mustNot(hasParentQuery("parent", boolQuery().should(queryStringQuery("p_field:*"))))).execute() .actionGet(); assertNoFailures(searchResponse); - - searchResponse = client().prepareSearch("test").setSearchType(SearchType.DFS_QUERY_THEN_FETCH) - .setQuery(boolQuery().mustNot(topChildrenQuery("child", boolQuery().should(queryStringQuery("c_field:*"))))).execute() - .actionGet(); - assertNoFailures(searchResponse); - } - - @Test - public void testFixAOBEIfTopChildrenIsWrappedInMusNotClause() throws Exception { - assertAcked(prepareCreate("test") - .addMapping("parent") - .addMapping("child", "_parent", "type=parent")); - ensureGreen(); - - // index simple data - client().prepareIndex("test", "parent", "p1").setSource("p_field", "p_value1").get(); - client().prepareIndex("test", "child", "c1").setSource("c_field", "red").setParent("p1").get(); - client().prepareIndex("test", "child", "c2").setSource("c_field", "yellow").setParent("p1").get(); - client().prepareIndex("test", "parent", "p2").setSource("p_field", "p_value2").get(); - client().prepareIndex("test", "child", "c3").setSource("c_field", "blue").setParent("p2").get(); - client().prepareIndex("test", "child", "c4").setSource("c_field", "red").setParent("p2").get(); - - refresh(); - - SearchResponse searchResponse = client().prepareSearch("test").setSearchType(SearchType.QUERY_THEN_FETCH) - .setQuery(boolQuery().mustNot(topChildrenQuery("child", boolQuery().should(queryStringQuery("c_field:*"))))).execute() - .actionGet(); - assertNoFailures(searchResponse); - } - - @Test - public void testTopChildrenReSearchBug() throws Exception { - assertAcked(prepareCreate("test") - .addMapping("parent") - .addMapping("child", "_parent", "type=parent")); - ensureGreen(); - int numberOfParents = 4; - int numberOfChildrenPerParent = 123; - for (int i = 1; i <= numberOfParents; i++) { - String parentId = String.format(Locale.ROOT, "p%d", i); - client().prepareIndex("test", "parent", parentId).setSource("p_field", String.format(Locale.ROOT, "p_value%d", i)).execute() - .actionGet(); - for (int j = 1; j <= numberOfChildrenPerParent; j++) { - client().prepareIndex("test", "child", String.format(Locale.ROOT, "%s_c%d", parentId, j)) - .setSource("c_field1", parentId, "c_field2", i % 2 == 0 ? "even" : "not_even").setParent(parentId).execute() - .actionGet(); - } - } - - refresh(); - - SearchResponse searchResponse = client().prepareSearch("test").setQuery(topChildrenQuery("child", termQuery("c_field1", "p3"))) - .get(); - assertNoFailures(searchResponse); - assertThat(searchResponse.getHits().totalHits(), equalTo(1l)); - assertThat(searchResponse.getHits().getAt(0).id(), equalTo("p3")); - - searchResponse = client().prepareSearch("test").setQuery(topChildrenQuery("child", termQuery("c_field2", "even"))).execute() - .actionGet(); - assertNoFailures(searchResponse); - assertThat(searchResponse.getHits().totalHits(), equalTo(2l)); - assertThat(searchResponse.getHits().getAt(0).id(), anyOf(equalTo("p2"), equalTo("p4"))); - assertThat(searchResponse.getHits().getAt(1).id(), anyOf(equalTo("p2"), equalTo("p4"))); } @Test @@ -781,11 +658,7 @@ public void testCountApiUsage() throws Exception { client().prepareIndex("test", "child", "c1").setSource("c_field", "1").setParent(parentId).get(); refresh(); - CountResponse countResponse = client().prepareCount("test").setQuery(topChildrenQuery("child", termQuery("c_field", "1"))) - .get(); - assertHitCount(countResponse, 1l); - - countResponse = client().prepareCount("test").setQuery(hasChildQuery("child", termQuery("c_field", "1")).scoreType("max")) + CountResponse countResponse = client().prepareCount("test").setQuery(hasChildQuery("child", termQuery("c_field", "1")).scoreType("max")) .get(); assertHitCount(countResponse, 1l); @@ -815,13 +688,6 @@ public void testExplainUsage() throws Exception { refresh(); SearchResponse searchResponse = client().prepareSearch("test") - .setExplain(true) - .setQuery(topChildrenQuery("child", termQuery("c_field", "1"))) - .get(); - assertHitCount(searchResponse, 1l); - assertThat(searchResponse.getHits().getAt(0).explanation().getDescription(), equalTo("not implemented yet...")); - - searchResponse = client().prepareSearch("test") .setExplain(true) .setQuery(hasChildQuery("child", termQuery("c_field", "1")).scoreType("max")) .get(); @@ -1061,10 +927,6 @@ public void testHasChildAndHasParentWrappedInAQueryFilter() throws Exception { .setQuery(filteredQuery(matchAllQuery(), hasChildQuery("child", matchQuery("c_field", 1)))).get(); assertSearchHit(searchResponse, 1, hasId("1")); - searchResponse = client().prepareSearch("test") - .setQuery(filteredQuery(matchAllQuery(), topChildrenQuery("child", matchQuery("c_field", 1)))).get(); - assertSearchHit(searchResponse, 1, hasId("1")); - searchResponse = client().prepareSearch("test") .setQuery(filteredQuery(matchAllQuery(), hasParentQuery("parent", matchQuery("p_field", 1)))).get(); assertSearchHit(searchResponse, 1, hasId("2")); @@ -1073,10 +935,6 @@ public void testHasChildAndHasParentWrappedInAQueryFilter() throws Exception { .setQuery(filteredQuery(matchAllQuery(), boolQuery().must(hasChildQuery("child", matchQuery("c_field", 1))))).get(); assertSearchHit(searchResponse, 1, hasId("1")); - searchResponse = client().prepareSearch("test") - .setQuery(filteredQuery(matchAllQuery(), boolQuery().must(topChildrenQuery("child", matchQuery("c_field", 1))))).get(); - assertSearchHit(searchResponse, 1, hasId("1")); - searchResponse = client().prepareSearch("test") .setQuery(filteredQuery(matchAllQuery(), boolQuery().must(hasParentQuery("parent", matchQuery("p_field", 1))))).get(); assertSearchHit(searchResponse, 1, hasId("2")); @@ -1085,10 +943,6 @@ public void testHasChildAndHasParentWrappedInAQueryFilter() throws Exception { @Test public void testSimpleQueryRewrite() throws Exception { assertAcked(prepareCreate("test") - //top_children query needs at least 2 shards for the totalHits to be accurate - .setSettings(settingsBuilder() - .put(indexSettings()) - .put(IndexMetaData.SETTING_NUMBER_OF_SHARDS, between(2, DEFAULT_MAX_NUM_SHARDS))) .addMapping("parent", "p_field", "type=string") .addMapping("child", "_parent", "type=parent", "c_field", "type=string")); ensureGreen(); @@ -1130,17 +984,6 @@ public void testSimpleQueryRewrite() throws Exception { assertThat(searchResponse.getHits().hits()[2].id(), equalTo("c002")); assertThat(searchResponse.getHits().hits()[3].id(), equalTo("c003")); assertThat(searchResponse.getHits().hits()[4].id(), equalTo("c004")); - - searchResponse = client().prepareSearch("test").setSearchType(searchType) - .setQuery(topChildrenQuery("child", prefixQuery("c_field", "c")).factor(10)).addSort("p_field", SortOrder.ASC).setSize(5) - .get(); - assertNoFailures(searchResponse); - assertThat(searchResponse.getHits().totalHits(), equalTo(10L)); - assertThat(searchResponse.getHits().hits()[0].id(), equalTo("p000")); - assertThat(searchResponse.getHits().hits()[1].id(), equalTo("p001")); - assertThat(searchResponse.getHits().hits()[2].id(), equalTo("p002")); - assertThat(searchResponse.getHits().hits()[3].id(), equalTo("p003")); - assertThat(searchResponse.getHits().hits()[4].id(), equalTo("p004")); } } @@ -1466,59 +1309,6 @@ public void testAddingParentToExistingMapping() throws IOException { } } - @Test @Slow - // The SimpleIdReaderTypeCache#docById method used lget, which can't be used if a map is shared. - public void testTopChildrenBug_concurrencyIssue() throws Exception { - assertAcked(prepareCreate("test") - .addMapping("parent") - .addMapping("child", "_parent", "type=parent")); - ensureGreen(); - - // index simple data - client().prepareIndex("test", "parent", "p1").setSource("p_field", "p_value1").get(); - client().prepareIndex("test", "parent", "p2").setSource("p_field", "p_value2").get(); - client().prepareIndex("test", "child", "c1").setParent("p1").setSource("c_field", "blue").get(); - client().prepareIndex("test", "child", "c2").setParent("p1").setSource("c_field", "red").get(); - client().prepareIndex("test", "child", "c3").setParent("p2").setSource("c_field", "red").get(); - client().admin().indices().prepareRefresh("test").get(); - - int numThreads = 10; - final CountDownLatch latch = new CountDownLatch(numThreads); - final AtomicReference holder = new AtomicReference<>(); - Runnable r = new Runnable() { - @Override - public void run() { - try { - for (int i = 0; i < 100; i++) { - SearchResponse searchResponse = client().prepareSearch("test") - .setQuery(topChildrenQuery("child", termQuery("c_field", "blue"))) - .get(); - assertNoFailures(searchResponse); - assertThat(searchResponse.getHits().totalHits(), equalTo(1l)); - - searchResponse = client().prepareSearch("test") - .setQuery(topChildrenQuery("child", termQuery("c_field", "red"))) - .get(); - assertNoFailures(searchResponse); - assertThat(searchResponse.getHits().totalHits(), equalTo(2l)); - } - } catch (AssertionError error) { - holder.set(error); - } finally { - latch.countDown(); - } - } - }; - - for (int i = 0; i < 10; i++) { - new Thread(r).start(); - } - latch.await(); - if (holder.get() != null) { - throw holder.get(); - } - } - @Test public void testHasChildQueryWithNestedInnerObjects() throws Exception { assertAcked(prepareCreate("test") @@ -1573,14 +1363,7 @@ public void testNamedFilters() throws Exception { client().prepareIndex("test", "child", "c1").setSource("c_field", "1").setParent(parentId).get(); refresh(); - SearchResponse searchResponse = client().prepareSearch("test").setQuery(topChildrenQuery("child", termQuery("c_field", "1")).queryName("test")) - .get(); - System.out.println(searchResponse); - assertHitCount(searchResponse, 1l); - assertThat(searchResponse.getHits().getAt(0).getMatchedQueries().length, equalTo(1)); - assertThat(searchResponse.getHits().getAt(0).getMatchedQueries()[0], equalTo("test")); - - searchResponse = client().prepareSearch("test").setQuery(hasChildQuery("child", termQuery("c_field", "1")).scoreType("max").queryName("test")) + SearchResponse searchResponse = client().prepareSearch("test").setQuery(hasChildQuery("child", termQuery("c_field", "1")).scoreType("max").queryName("test")) .get(); assertHitCount(searchResponse, 1l); assertThat(searchResponse.getHits().getAt(0).getMatchedQueries().length, equalTo(1)); @@ -1644,15 +1427,6 @@ public void testParentChildQueriesNoParentType() throws Exception { assertThat(e.status(), equalTo(RestStatus.BAD_REQUEST)); } - try { - client().prepareSearch("test") - .setQuery(topChildrenQuery("child", termQuery("c_field", "1")).score("max")) - .get(); - fail(); - } catch (SearchPhaseExecutionException e) { - assertThat(e.status(), equalTo(RestStatus.BAD_REQUEST)); - } - try { client().prepareSearch("test") .setQuery(hasParentQuery("parent", termQuery("p_field", "1")).scoreType("score")) @@ -1710,12 +1484,6 @@ public void testAdd_ParentFieldAfterIndexingParentDocButBeforeIndexingChildDoc() assertHitCount(searchResponse, 1l); assertSearchHits(searchResponse, parentId); - searchResponse = client().prepareSearch("test") - .setQuery(topChildrenQuery("child", termQuery("c_field", "1")).score("max")) - .get(); - assertHitCount(searchResponse, 1l); - assertSearchHits(searchResponse, parentId); - searchResponse = client().prepareSearch("test") .setPostFilter(hasParentQuery("parent", termQuery("p_field", "1"))) .get(); @@ -1795,8 +1563,7 @@ public void testParentChildQueriesViaScrollApi() throws Exception { hasChildQuery("child", matchAllQuery()), filteredQuery(matchAllQuery(), hasChildQuery("child", matchAllQuery())), hasParentQuery("parent", matchAllQuery()), - filteredQuery(matchAllQuery(), hasParentQuery("parent", matchAllQuery())), - topChildrenQuery("child", matchAllQuery()).factor(10) + filteredQuery(matchAllQuery(), hasParentQuery("parent", matchAllQuery())) }; for (QueryBuilder query : queries) {