Skip to content

Commit

Permalink
Fix nested document support in percolator query (#58149)
Browse files Browse the repository at this point in the history
This commit ensures that we filter out nested documents
when retrieving the document slots of a matching query.

Closes #52850
  • Loading branch information
jimczi committed Jun 17, 2020
1 parent de05b57 commit dee5c62
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 10 deletions.
Expand Up @@ -20,6 +20,8 @@

import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.index.ReaderUtil;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreMode;
Expand Down Expand Up @@ -70,8 +72,8 @@ static void innerHitsExecute(Query mainQuery,
for (PercolateQuery percolateQuery : percolateQueries) {
String fieldName = singlePercolateQuery ? FIELD_NAME_PREFIX : FIELD_NAME_PREFIX + "_" + percolateQuery.getName();
IndexSearcher percolatorIndexSearcher = percolateQuery.getPercolatorIndexSearcher();
Weight weight = percolatorIndexSearcher.createWeight(percolatorIndexSearcher.rewrite(Queries.newNonNestedFilter()),
ScoreMode.COMPLETE_NO_SCORES, 1f);
Query nonNestedFilter = percolatorIndexSearcher.rewrite(Queries.newNonNestedFilter());
Weight weight = percolatorIndexSearcher.createWeight(nonNestedFilter, ScoreMode.COMPLETE_NO_SCORES, 1f);
Scorer s = weight.scorer(percolatorIndexSearcher.getIndexReader().leaves().get(0));
int memoryIndexMaxDoc = percolatorIndexSearcher.getIndexReader().maxDoc();
BitSet rootDocs = BitSet.of(s.iterator(), memoryIndexMaxDoc);
Expand All @@ -91,6 +93,13 @@ static void innerHitsExecute(Query mainQuery,
// This is not a document with a percolator field.
continue;
}
if (hasNestedDocs) {
// Ensures that we filter out nested documents
query = new BooleanQuery.Builder()
.add(query, BooleanClause.Occur.MUST)
.add(nonNestedFilter, BooleanClause.Occur.FILTER)
.build();
}

TopDocs topDocs = percolatorIndexSearcher.search(query, memoryIndexMaxDoc, new Sort(SortField.FIELD_DOC));
if (topDocs.totalHits.value == 0) {
Expand Down
Expand Up @@ -740,23 +740,32 @@ public void testWithMultiplePercolatorFields() throws Exception {
public void testPercolateQueryWithNestedDocuments() throws Exception {
XContentBuilder mapping = XContentFactory.jsonBuilder();
mapping.startObject().startObject("properties").startObject("query").field("type", "percolator").endObject()
.startObject("id").field("type", "keyword").endObject()
.startObject("companyname").field("type", "text").endObject().startObject("employee").field("type", "nested")
.startObject("properties").startObject("name").field("type", "text").endObject().endObject().endObject().endObject()
.endObject();
assertAcked(client().admin().indices().prepareCreate("test")
.setMapping(mapping)
);
client().prepareIndex("test").setId("q1").setSource(jsonBuilder().startObject()
.field("id", "q1")
.field("query", QueryBuilders.nestedQuery("employee",
QueryBuilders.matchQuery("employee.name", "virginia potts").operator(Operator.AND), ScoreMode.Avg)
).endObject())
.get();
// this query should never match as it doesn't use nested query:
client().prepareIndex("test").setId("q2").setSource(jsonBuilder().startObject()
.field("id", "q2")
.field("query", QueryBuilders.matchQuery("employee.name", "virginia")).endObject())
.get();
client().admin().indices().prepareRefresh().get();

client().prepareIndex("test").setId("q3").setSource(jsonBuilder().startObject()
.field("id", "q3")
.field("query", QueryBuilders.matchAllQuery()).endObject())
.get();
client().admin().indices().prepareRefresh().get();

SearchResponse response = client().prepareSearch()
.setQuery(new PercolateQueryBuilder("query",
BytesReference.bytes(XContentFactory.jsonBuilder()
Expand All @@ -766,10 +775,11 @@ public void testPercolateQueryWithNestedDocuments() throws Exception {
.startObject().field("name", "tony stark").endObject()
.endArray()
.endObject()), XContentType.JSON))
.addSort("_doc", SortOrder.ASC)
.addSort("id", SortOrder.ASC)
.get();
assertHitCount(response, 1);
assertHitCount(response, 2);
assertThat(response.getHits().getAt(0).getId(), equalTo("q1"));
assertThat(response.getHits().getAt(1).getId(), equalTo("q3"));

response = client().prepareSearch()
.setQuery(new PercolateQueryBuilder("query",
Expand All @@ -780,17 +790,19 @@ public void testPercolateQueryWithNestedDocuments() throws Exception {
.startObject().field("name", "tony stark").endObject()
.endArray()
.endObject()), XContentType.JSON))
.addSort("_doc", SortOrder.ASC)
.addSort("id", SortOrder.ASC)
.get();
assertHitCount(response, 0);
assertHitCount(response, 1);
assertThat(response.getHits().getAt(0).getId(), equalTo("q3"));

response = client().prepareSearch()
.setQuery(new PercolateQueryBuilder("query",
BytesReference.bytes(XContentFactory.jsonBuilder().startObject().field("companyname", "notstark").endObject()),
XContentType.JSON))
.addSort("_doc", SortOrder.ASC)
.addSort("id", SortOrder.ASC)
.get();
assertHitCount(response, 0);
assertHitCount(response, 1);
assertThat(response.getHits().getAt(0).getId(), equalTo("q3"));

response = client().prepareSearch()
.setQuery(new PercolateQueryBuilder("query", Arrays.asList(
Expand All @@ -807,13 +819,21 @@ public void testPercolateQueryWithNestedDocuments() throws Exception {
.startObject().field("name", "peter parker").endObject()
.startObject().field("name", "virginia potts").endObject()
.endArray()
.endObject()),
BytesReference.bytes(XContentFactory.jsonBuilder()
.startObject().field("companyname", "stark")
.startArray("employee")
.startObject().field("name", "peter parker").endObject()
.endArray()
.endObject())
), XContentType.JSON))
.addSort("_doc", SortOrder.ASC)
.addSort("id", SortOrder.ASC)
.get();
assertHitCount(response, 1);
assertHitCount(response, 2);
assertThat(response.getHits().getAt(0).getId(), equalTo("q1"));
assertThat(response.getHits().getAt(0).getFields().get("_percolator_document_slot").getValues(), equalTo(Arrays.asList(0, 1)));
assertThat(response.getHits().getAt(1).getId(), equalTo("q3"));
assertThat(response.getHits().getAt(1).getFields().get("_percolator_document_slot").getValues(), equalTo(Arrays.asList(0, 1, 2)));
}

public void testPercolatorQueryViaMultiSearch() throws Exception {
Expand Down

0 comments on commit dee5c62

Please sign in to comment.