Tying it all together
Let’s put our custom query type to work.
After indexing documents 0-999, we create a twoAndFive
query, similar to what we did in BooleanQueryIntro
,
but this time it’s using the logic implemented above.
When the IndexSearcher
(or technically the DefaultBulkScorer
) first calls nextDoc
on our
DocIdSetIterator
, the left iterator (“two) will step to its first match – document 2. Then the right (“five”)
iterator steps to its first match greater than or equal to 2 – document 5. Then the left iterator advances to
document 6. Then the right iterator advances to document 10. Finally, the left iterator advances to document 10
too, and we return it. (It’s the first hit in the returned TopDocs
.)
The logic for the next (and every other) matching document is similar:
left=12
right=15
left=16
right=20 <--
left=20 <-- HIT
After returning the top 10 hits, we can take a look at the explain
output to see the output from our
custom Weight
and custom Similarity
.
public static void main(String[] args) throws IOException {
Path tmpDir = Files.createTempDirectory(BooleanQueryIntro.class.getSimpleName());
try (Directory directory = FSDirectory.open(tmpDir);
IndexWriter writer = new IndexWriter(directory, new IndexWriterConfig())) {
for (String doc : createDocumentText(1000)) {
writer.addDocument(List.of(new TextField("text", doc, Field.Store.NO)));
}
try (IndexReader reader = DirectoryReader.open(writer)) {
IndexSearcher searcher = new IndexSearcher(reader);
searcher.setSimilarity(new CountMatchingClauseSimilarity());
BinaryAndQuery twoAndFive = new BinaryAndQuery(
new TermQuery(new Term("text", "two")),
new TermQuery(new Term("text", "five"))
);
System.out.println(twoAndFive);
TopDocs topDocs = searcher.search(twoAndFive, 10);
for (ScoreDoc scoreDoc : topDocs.scoreDocs) {
System.out.println(scoreDoc.doc + " " + scoreDoc.score);
}
System.out.println(searcher.explain(twoAndFive, 20));
System.out.println(searcher.explain(twoAndFive, 22));
}
} finally {
for (String indexFile : FSDirectory.listAll(tmpDir)) {
Files.deleteIfExists(tmpDir.resolve(indexFile));
}
Files.deleteIfExists(tmpDir);
}
}
}