Add random filter that compares XBooleanFilter with BooleanQuery while respective the min_should_match = 1 that the filter applies
This commit is contained in:
parent
1e06c76467
commit
904c0abb3e
|
@ -7,20 +7,18 @@ import org.apache.lucene.document.StringField;
|
||||||
import org.apache.lucene.index.*;
|
import org.apache.lucene.index.*;
|
||||||
import org.apache.lucene.queries.FilterClause;
|
import org.apache.lucene.queries.FilterClause;
|
||||||
import org.apache.lucene.queries.TermFilter;
|
import org.apache.lucene.queries.TermFilter;
|
||||||
import org.apache.lucene.search.BooleanClause;
|
import org.apache.lucene.search.*;
|
||||||
import org.apache.lucene.search.DocIdSet;
|
|
||||||
import org.apache.lucene.search.FieldCacheTermsFilter;
|
|
||||||
import org.apache.lucene.search.Filter;
|
|
||||||
import org.apache.lucene.store.Directory;
|
import org.apache.lucene.store.Directory;
|
||||||
import org.apache.lucene.store.RAMDirectory;
|
|
||||||
import org.apache.lucene.util.FixedBitSet;
|
import org.apache.lucene.util.FixedBitSet;
|
||||||
import org.elasticsearch.common.lucene.Lucene;
|
import org.elasticsearch.common.lucene.Lucene;
|
||||||
import org.elasticsearch.test.ElasticsearchTestCase;
|
import org.elasticsearch.test.ElasticsearchLuceneTestCase;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static org.apache.lucene.search.BooleanClause.Occur.*;
|
import static org.apache.lucene.search.BooleanClause.Occur.*;
|
||||||
|
@ -28,10 +26,11 @@ import static org.hamcrest.core.IsEqual.equalTo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
public class XBooleanFilterTests extends ElasticsearchTestCase {
|
public class XBooleanFilterTests extends ElasticsearchLuceneTestCase {
|
||||||
|
|
||||||
private Directory directory;
|
private Directory directory;
|
||||||
private AtomicReader reader;
|
private AtomicReader reader;
|
||||||
|
private static final char[] distinctValues = new char[] {'a', 'b', 'c', 'd', 'v','z','y'};
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setup() throws Exception {
|
public void setup() throws Exception {
|
||||||
|
@ -50,7 +49,7 @@ public class XBooleanFilterTests extends ElasticsearchTestCase {
|
||||||
}
|
}
|
||||||
documents.add(document);
|
documents.add(document);
|
||||||
}
|
}
|
||||||
directory = new RAMDirectory();
|
directory = newDirectory();
|
||||||
IndexWriter w = new IndexWriter(directory, new IndexWriterConfig(Lucene.VERSION, new KeywordAnalyzer()));
|
IndexWriter w = new IndexWriter(directory, new IndexWriterConfig(Lucene.VERSION, new KeywordAnalyzer()));
|
||||||
w.addDocuments(documents);
|
w.addDocuments(documents);
|
||||||
w.close();
|
w.close();
|
||||||
|
@ -59,9 +58,10 @@ public class XBooleanFilterTests extends ElasticsearchTestCase {
|
||||||
|
|
||||||
@After
|
@After
|
||||||
public void tearDown() throws Exception {
|
public void tearDown() throws Exception {
|
||||||
super.tearDown();
|
|
||||||
reader.close();
|
reader.close();
|
||||||
directory.close();
|
directory.close();
|
||||||
|
super.tearDown();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -348,7 +348,7 @@ public class XBooleanFilterTests extends ElasticsearchTestCase {
|
||||||
private static FilterClause newFilterClause(int field, char character, BooleanClause.Occur occur, boolean slowerBitsBackedFilter) {
|
private static FilterClause newFilterClause(int field, char character, BooleanClause.Occur occur, boolean slowerBitsBackedFilter) {
|
||||||
Filter filter;
|
Filter filter;
|
||||||
if (slowerBitsBackedFilter) {
|
if (slowerBitsBackedFilter) {
|
||||||
filter = new FieldCacheTermsFilter(String.valueOf(field), String.valueOf(character));
|
filter = new PrettyPrintFieldCacheTermsFilter(String.valueOf(field), String.valueOf(character));
|
||||||
} else {
|
} else {
|
||||||
Term term = new Term(String.valueOf(field), String.valueOf(character));
|
Term term = new Term(String.valueOf(field), String.valueOf(character));
|
||||||
filter = new TermFilter(term);
|
filter = new TermFilter(term);
|
||||||
|
@ -364,4 +364,106 @@ public class XBooleanFilterTests extends ElasticsearchTestCase {
|
||||||
return booleanFilter;
|
return booleanFilter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@AwaitsFix(bugUrl = "https://github.com/elasticsearch/elasticsearch/pull/4144/")
|
||||||
|
public void testRandom() throws IOException {
|
||||||
|
int iterations = atLeast(400); // don't worry that is fast!
|
||||||
|
for (int iter = 0; iter < iterations; iter++) {
|
||||||
|
int numClauses = 1 + random().nextInt(10);
|
||||||
|
FilterClause[] clauses = new FilterClause[numClauses];
|
||||||
|
BooleanQuery topLevel = new BooleanQuery();
|
||||||
|
BooleanQuery orQuery = new BooleanQuery();
|
||||||
|
boolean hasMust = false;
|
||||||
|
boolean hasShould = false;
|
||||||
|
boolean hasMustNot = false;
|
||||||
|
for(int i = 0; i < numClauses; i++) {
|
||||||
|
int field = random().nextInt(5);
|
||||||
|
char value = distinctValues[random().nextInt(distinctValues.length)];
|
||||||
|
switch(random().nextInt(10)) {
|
||||||
|
case 9:
|
||||||
|
case 8:
|
||||||
|
case 7:
|
||||||
|
case 6:
|
||||||
|
case 5:
|
||||||
|
hasMust = true;
|
||||||
|
clauses[i] = newFilterClause(field, value, MUST, random().nextBoolean());
|
||||||
|
topLevel.add(new BooleanClause(new TermQuery(new Term(String.valueOf(field), String.valueOf(value))), MUST));
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
case 3:
|
||||||
|
case 2:
|
||||||
|
case 1:
|
||||||
|
hasShould = true;
|
||||||
|
clauses[i] = newFilterClause(field, value, SHOULD, random().nextBoolean());
|
||||||
|
orQuery.add(new BooleanClause(new TermQuery(new Term(String.valueOf(field), String.valueOf(value))), SHOULD));
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
hasMustNot = true;
|
||||||
|
clauses[i] = newFilterClause(field, value, MUST_NOT, random().nextBoolean());
|
||||||
|
topLevel.add(new BooleanClause(new TermQuery(new Term(String.valueOf(field), String.valueOf(value))), MUST_NOT));
|
||||||
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if (orQuery.getClauses().length > 0) {
|
||||||
|
topLevel.add(new BooleanClause(orQuery, MUST));
|
||||||
|
}
|
||||||
|
if (hasMustNot && !hasMust && !hasShould) { // pure negative
|
||||||
|
topLevel.add(new BooleanClause(new MatchAllDocsQuery(), MUST));
|
||||||
|
}
|
||||||
|
XBooleanFilter booleanFilter = createBooleanFilter(clauses);
|
||||||
|
|
||||||
|
FixedBitSet leftResult = new FixedBitSet(reader.maxDoc());
|
||||||
|
FixedBitSet rightResult = new FixedBitSet(reader.maxDoc());
|
||||||
|
DocIdSet left = booleanFilter.getDocIdSet(reader.getContext(), reader.getLiveDocs());
|
||||||
|
DocIdSet right = new QueryWrapperFilter(topLevel).getDocIdSet(reader.getContext(), reader.getLiveDocs());
|
||||||
|
if (left == null || right == null) {
|
||||||
|
if (left == null && right != null) {
|
||||||
|
assertThat(errorMsg(clauses, topLevel), (right.iterator() == null ? DocIdSetIterator.NO_MORE_DOCS : right.iterator().nextDoc()), equalTo(DocIdSetIterator.NO_MORE_DOCS));
|
||||||
|
}
|
||||||
|
if (left != null && right == null) {
|
||||||
|
assertThat(errorMsg(clauses, topLevel), (left.iterator() == null ? DocIdSetIterator.NO_MORE_DOCS : left.iterator().nextDoc()), equalTo(DocIdSetIterator.NO_MORE_DOCS));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
DocIdSetIterator leftIter = left.iterator();
|
||||||
|
DocIdSetIterator rightIter = right.iterator();
|
||||||
|
if (leftIter != null) {
|
||||||
|
leftResult.or(leftIter);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rightIter != null) {
|
||||||
|
rightResult.or(rightIter);
|
||||||
|
}
|
||||||
|
|
||||||
|
assertThat(leftResult.cardinality(), equalTo(leftResult.cardinality()));
|
||||||
|
for (int i = 0; i < reader.maxDoc(); i++) {
|
||||||
|
assertThat(errorMsg(clauses, topLevel) + " -- failed at index " + i, leftResult.get(i), equalTo(rightResult.get(i)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String errorMsg(FilterClause[] clauses, BooleanQuery query) {
|
||||||
|
return query.toString() + " vs. " + Arrays.toString(clauses);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static final class PrettyPrintFieldCacheTermsFilter extends FieldCacheTermsFilter {
|
||||||
|
|
||||||
|
private final String value;
|
||||||
|
private final String field;
|
||||||
|
|
||||||
|
public PrettyPrintFieldCacheTermsFilter(String field, String value) {
|
||||||
|
super(field, value);
|
||||||
|
this.field = field;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "SLOW(" + field + ":" + value + ")";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue