Plain highlighter should ignore parent/child queries.
The plain highligher fails when it tries to select the fragments based on a query containing either a `has_child` or `has_parent` query. The plain highligher should just ignore parent/child queries as it makes no sense to highligh a parent match with a has_child as the child documents are not available at highlight time. Instead if child document should be highlighed inner hits should be used. Parent/child queries already have no effect when the `fvh` or `postings` highligher is used. The test added in this commit verifies that. Closes #14999
This commit is contained in:
parent
502217f035
commit
72e0d422e9
|
@ -352,7 +352,17 @@ public class HasChildQueryBuilder extends AbstractQueryBuilder<HasChildQueryBuil
|
|||
parentType, scoreMode, parentChildIndexFieldData, context.getSearchSimilarity());
|
||||
}
|
||||
|
||||
static final class LateParsingQuery extends Query {
|
||||
/**
|
||||
* A query that rewrites into another query using
|
||||
* {@link JoinUtil#createJoinQuery(String, Query, Query, IndexSearcher, ScoreMode, MultiDocValues.OrdinalMap, int, int)}
|
||||
* that executes the actual join.
|
||||
*
|
||||
* This query is exclusively used by the {@link HasChildQueryBuilder} and {@link HasParentQueryBuilder} to get access
|
||||
* to the {@link DirectoryReader} used by the current search in order to retrieve the {@link MultiDocValues.OrdinalMap}.
|
||||
* The {@link MultiDocValues.OrdinalMap} is required by {@link JoinUtil} to execute the join.
|
||||
*/
|
||||
// TODO: Find a way to remove this query and let doToQuery(...) just return the query from JoinUtil.createJoinQuery(...)
|
||||
public static final class LateParsingQuery extends Query {
|
||||
|
||||
private final Query toQuery;
|
||||
private final Query innerQuery;
|
||||
|
|
|
@ -27,6 +27,7 @@ import org.apache.lucene.search.highlight.WeightedSpanTermExtractor;
|
|||
import org.apache.lucene.spatial.geopoint.search.GeoPointInBBoxQuery;
|
||||
import org.elasticsearch.common.lucene.search.function.FiltersFunctionScoreQuery;
|
||||
import org.elasticsearch.common.lucene.search.function.FunctionScoreQuery;
|
||||
import org.elasticsearch.index.query.HasChildQueryBuilder;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
@ -89,11 +90,16 @@ public final class CustomQueryScorer extends QueryScorer {
|
|||
}
|
||||
|
||||
protected void extract(Query query, float boost, Map<String, WeightedSpanTerm> terms) throws IOException {
|
||||
if (query instanceof GeoPointInBBoxQuery) {
|
||||
// skip all geo queries, see https://issues.apache.org/jira/browse/LUCENE-7293 and
|
||||
// https://github.com/elastic/elasticsearch/issues/17537
|
||||
if (query instanceof GeoPointInBBoxQuery == false) {
|
||||
return;
|
||||
} else if (query instanceof HasChildQueryBuilder.LateParsingQuery) {
|
||||
// skip has_child or has_parent queries, see: https://github.com/elastic/elasticsearch/issues/14999
|
||||
return;
|
||||
}
|
||||
|
||||
super.extract(query, boost, terms);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,8 +32,12 @@ import org.elasticsearch.common.lucene.search.function.FiltersFunctionScoreQuery
|
|||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.unit.TimeValue;
|
||||
import org.elasticsearch.index.IndexModule;
|
||||
import org.elasticsearch.index.query.BoolQueryBuilder;
|
||||
import org.elasticsearch.index.query.HasChildQueryBuilder;
|
||||
import org.elasticsearch.index.query.HasParentQueryBuilder;
|
||||
import org.elasticsearch.index.query.IdsQueryBuilder;
|
||||
import org.elasticsearch.index.query.MatchAllQueryBuilder;
|
||||
import org.elasticsearch.index.query.MatchQueryBuilder;
|
||||
import org.elasticsearch.index.query.QueryBuilder;
|
||||
import org.elasticsearch.index.query.QueryBuilders;
|
||||
import org.elasticsearch.index.query.functionscore.FunctionScoreQueryBuilder;
|
||||
|
@ -43,6 +47,8 @@ import org.elasticsearch.search.aggregations.bucket.filter.Filter;
|
|||
import org.elasticsearch.search.aggregations.bucket.global.Global;
|
||||
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
|
||||
import org.elasticsearch.search.builder.SearchSourceBuilder;
|
||||
import org.elasticsearch.search.highlight.HighlightBuilder;
|
||||
import org.elasticsearch.search.highlight.HighlightField;
|
||||
import org.elasticsearch.search.sort.SortBuilders;
|
||||
import org.elasticsearch.search.sort.SortOrder;
|
||||
import org.elasticsearch.test.ESIntegTestCase;
|
||||
|
@ -1889,4 +1895,43 @@ public class ChildQuerySearchIT extends ESIntegTestCase {
|
|||
QueryBuilders.hasChildQuery("child-type", new IdsQueryBuilder().addIds("child-id"), ScoreMode.None)).get();
|
||||
assertSearchHits(searchResponse, "parent-id");
|
||||
}
|
||||
|
||||
public void testHighlighersIgnoreParentChild() {
|
||||
assertAcked(prepareCreate("test")
|
||||
.addMapping("parent-type", "searchText", "type=text,term_vector=with_positions_offsets,index_options=offsets")
|
||||
.addMapping("child-type", "_parent", "type=parent-type", "searchText",
|
||||
"type=text,term_vector=with_positions_offsets,index_options=offsets"));
|
||||
client().prepareIndex("test", "parent-type", "parent-id").setSource("searchText", "quick brown fox").get();
|
||||
client().prepareIndex("test", "child-type", "child-id").setParent("parent-id").setSource("searchText", "quick brown fox").get();
|
||||
refresh();
|
||||
|
||||
String[] highlightTypes = new String[] {"plain", "fvh", "postings"};
|
||||
for (String highlightType : highlightTypes) {
|
||||
logger.info("Testing with highlight type [{}]", highlightType);
|
||||
SearchResponse searchResponse = client().prepareSearch("test")
|
||||
.setQuery(new BoolQueryBuilder()
|
||||
.must(new MatchQueryBuilder("searchText", "fox"))
|
||||
.must(new HasChildQueryBuilder("child-type", new MatchAllQueryBuilder(), ScoreMode.None))
|
||||
)
|
||||
.highlighter(new HighlightBuilder().field(new HighlightBuilder.Field("searchText").highlighterType(highlightType)))
|
||||
.get();
|
||||
assertHitCount(searchResponse, 1);
|
||||
assertThat(searchResponse.getHits().getAt(0).id(), equalTo("parent-id"));
|
||||
HighlightField highlightField = searchResponse.getHits().getAt(0).getHighlightFields().get("searchText");
|
||||
assertThat(highlightField.getFragments()[0].string(), equalTo("quick brown <em>fox</em>"));
|
||||
|
||||
searchResponse = client().prepareSearch("test")
|
||||
.setQuery(new BoolQueryBuilder()
|
||||
.must(new MatchQueryBuilder("searchText", "fox"))
|
||||
.must(new HasParentQueryBuilder("parent-type", new MatchAllQueryBuilder(), false))
|
||||
)
|
||||
.highlighter(new HighlightBuilder().field(new HighlightBuilder.Field("searchText").highlighterType(highlightType)))
|
||||
.get();
|
||||
assertHitCount(searchResponse, 1);
|
||||
assertThat(searchResponse.getHits().getAt(0).id(), equalTo("child-id"));
|
||||
highlightField = searchResponse.getHits().getAt(0).getHighlightFields().get("searchText");
|
||||
assertThat(highlightField.getFragments()[0].string(), equalTo("quick brown <em>fox</em>"));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue