Skip to content

Commit c22b521

Browse files
committed
fix properly handling acceptDocs in filters
our idea is to apply it on the "filtered/constant" level, and not on compound filters, so we won't apply it multiple times. The solution is conservative a bit now, we can further optimize it in the future, for example, not to wrap it when no caching is done within the filter chain
1 parent 5a226cd commit c22b521

32 files changed

+971
-231
lines changed

src/main/java/org/apache/lucene/queryparser/classic/ExistsFieldQueryExtension.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
import org.apache.lucene.search.Filter;
2323
import org.apache.lucene.search.Query;
2424
import org.apache.lucene.search.TermRangeFilter;
25-
import org.elasticsearch.common.lucene.search.DeletionAwareConstantScoreQuery;
25+
import org.elasticsearch.common.lucene.search.XConstantScoreQuery;
2626
import org.elasticsearch.index.mapper.MapperService;
2727
import org.elasticsearch.index.query.QueryParseContext;
2828

@@ -54,6 +54,6 @@ public Query query(QueryParseContext parseContext, String queryText) {
5454

5555
filter = wrapSmartNameFilter(filter, smartNameFieldMappers, parseContext);
5656

57-
return new DeletionAwareConstantScoreQuery(filter);
57+
return new XConstantScoreQuery(filter);
5858
}
5959
}

src/main/java/org/apache/lucene/queryparser/classic/MissingFieldQueryExtension.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@
2222
import org.apache.lucene.search.Filter;
2323
import org.apache.lucene.search.Query;
2424
import org.apache.lucene.search.TermRangeFilter;
25-
import org.elasticsearch.common.lucene.search.DeletionAwareConstantScoreQuery;
2625
import org.elasticsearch.common.lucene.search.NotFilter;
26+
import org.elasticsearch.common.lucene.search.XConstantScoreQuery;
2727
import org.elasticsearch.index.mapper.MapperService;
2828
import org.elasticsearch.index.query.QueryParseContext;
2929

@@ -59,6 +59,6 @@ public Query query(QueryParseContext parseContext, String queryText) {
5959

6060
filter = wrapSmartNameFilter(filter, smartNameFieldMappers, parseContext);
6161

62-
return new DeletionAwareConstantScoreQuery(filter);
62+
return new XConstantScoreQuery(filter);
6363
}
6464
}

src/main/java/org/apache/lucene/search/vectorhighlight/CustomFieldQuery.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,7 @@
2424
import org.apache.lucene.queries.FilterClause;
2525
import org.apache.lucene.search.*;
2626
import org.apache.lucene.search.spans.SpanTermQuery;
27-
import org.elasticsearch.common.lucene.search.MultiPhrasePrefixQuery;
28-
import org.elasticsearch.common.lucene.search.TermFilter;
29-
import org.elasticsearch.common.lucene.search.XBooleanFilter;
30-
import org.elasticsearch.common.lucene.search.XTermsFilter;
27+
import org.elasticsearch.common.lucene.search.*;
3128
import org.elasticsearch.common.lucene.search.function.FiltersFunctionScoreQuery;
3229
import org.elasticsearch.common.lucene.search.function.FunctionScoreQuery;
3330

@@ -87,6 +84,9 @@ void flatten(Query sourceQuery, IndexReader reader, Collection<Query> flatQuerie
8784
} else if (sourceQuery instanceof FilteredQuery) {
8885
flatten(((FilteredQuery) sourceQuery).getQuery(), reader, flatQueries);
8986
flatten(((FilteredQuery) sourceQuery).getFilter(), reader, flatQueries);
87+
} else if (sourceQuery instanceof XFilteredQuery) {
88+
flatten(((XFilteredQuery) sourceQuery).getQuery(), reader, flatQueries);
89+
flatten(((XFilteredQuery) sourceQuery).getFilter(), reader, flatQueries);
9090
} else if (sourceQuery instanceof MultiPhrasePrefixQuery) {
9191
try {
9292
flatten(sourceQuery.rewrite(reader), reader, flatQueries);

src/main/java/org/elasticsearch/common/lucene/search/NotDeletedFilter.java renamed to src/main/java/org/elasticsearch/common/lucene/search/ApplyAcceptedDocsFilter.java

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,24 +20,23 @@
2020
package org.elasticsearch.common.lucene.search;
2121

2222
import org.apache.lucene.index.AtomicReaderContext;
23-
import org.apache.lucene.search.DocIdSet;
24-
import org.apache.lucene.search.DocIdSetIterator;
25-
import org.apache.lucene.search.Filter;
26-
import org.apache.lucene.search.FilteredDocIdSetIterator;
23+
import org.apache.lucene.search.*;
2724
import org.apache.lucene.util.Bits;
2825
import org.apache.lucene.util.FixedBitSet;
2926
import org.elasticsearch.common.lucene.docset.DocIdSets;
3027

3128
import java.io.IOException;
3229

3330
/**
34-
* A filter that filters out deleted documents.
31+
* The assumption is that the underlying filter might not apply the accepted docs, so this filter helps to wrap
32+
* the actual filter and apply the actual accepted docs.
3533
*/
36-
public class NotDeletedFilter extends Filter {
34+
// TODO: we can try and be smart, and only apply if if a filter is cached (down the "chain") since that's the only place that acceptDocs are not applied in ES
35+
public class ApplyAcceptedDocsFilter extends Filter {
3736

3837
private final Filter filter;
3938

40-
public NotDeletedFilter(Filter filter) {
39+
public ApplyAcceptedDocsFilter(Filter filter) {
4140
this.filter = filter;
4241
}
4342

@@ -47,10 +46,14 @@ public DocIdSet getDocIdSet(AtomicReaderContext context, Bits acceptDocs) throws
4746
if (DocIdSets.isEmpty(docIdSet)) {
4847
return null;
4948
}
50-
if (!context.reader().hasDeletions()) {
49+
if (acceptDocs == null) {
5150
return docIdSet;
5251
}
53-
return new NotDeletedDocIdSet(docIdSet, context.reader().getLiveDocs());
52+
if (acceptDocs == context.reader().getLiveDocs()) {
53+
// optimized wrapper for not deleted cases
54+
return new NotDeletedDocIdSet(docIdSet, acceptDocs);
55+
}
56+
return BitsFilteredDocIdSet.wrap(docIdSet, acceptDocs);
5457
}
5558

5659
public Filter filter() {
@@ -59,7 +62,7 @@ public Filter filter() {
5962

6063
@Override
6164
public String toString() {
62-
return "NotDeleted(" + filter + ")";
65+
return filter.toString();
6366
}
6467

6568
static class NotDeletedDocIdSet extends DocIdSet {

src/main/java/org/elasticsearch/common/lucene/search/Queries.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
public class Queries {
3333

3434
// We don't use MatchAllDocsQuery, its slower than the one below ... (much slower)
35-
public final static Query MATCH_ALL_QUERY = new DeletionAwareConstantScoreQuery(new MatchAllDocsFilter());
35+
public final static Query MATCH_ALL_QUERY = new XConstantScoreQuery(new MatchAllDocsFilter());
3636
public final static Query NO_MATCH_QUERY = MatchNoDocsQuery.INSTANCE;
3737

3838
/**
@@ -113,8 +113,8 @@ public static boolean isConstantMatchAllQuery(Query query) {
113113
if (query == Queries.MATCH_ALL_QUERY) {
114114
return true;
115115
}
116-
if (query instanceof DeletionAwareConstantScoreQuery) {
117-
DeletionAwareConstantScoreQuery scoreQuery = (DeletionAwareConstantScoreQuery) query;
116+
if (query instanceof XConstantScoreQuery) {
117+
XConstantScoreQuery scoreQuery = (XConstantScoreQuery) query;
118118
if (scoreQuery.getFilter() instanceof MatchAllDocsFilter) {
119119
return true;
120120
}
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,12 @@
2525
/**
2626
* We still need sometimes to exclude deletes, because we don't remove them always with acceptDocs on filters
2727
*/
28-
public class DeletionAwareConstantScoreQuery extends ConstantScoreQuery {
28+
public class XConstantScoreQuery extends ConstantScoreQuery {
2929

3030
private final Filter actualFilter;
3131

32-
public DeletionAwareConstantScoreQuery(Filter filter) {
33-
super(new NotDeletedFilter(filter));
32+
public XConstantScoreQuery(Filter filter) {
33+
super(new ApplyAcceptedDocsFilter(filter));
3434
this.actualFilter = filter;
3535
}
3636

0 commit comments

Comments
 (0)