From 9403372fbc36aced848bf8aa498bc71b7b94567b Mon Sep 17 00:00:00 2001 From: Alan Woodward Date: Sat, 14 Jan 2017 09:08:02 +0000 Subject: [PATCH] Add getMatchingChildren() method to Scorer --- lucene/CHANGES.txt | 4 +++ .../lucene/search/DisjunctionScorer.java | 8 +++++ .../search/MinShouldMatchSumScorer.java | 9 +++++ .../java/org/apache/lucene/search/Scorer.java | 8 +++++ .../TestBooleanQueryVisitSubscorers.java | 33 +++++++++++++++++++ 5 files changed, 62 insertions(+) diff --git a/lucene/CHANGES.txt b/lucene/CHANGES.txt index 58201d62919..540188e7825 100644 --- a/lucene/CHANGES.txt +++ b/lucene/CHANGES.txt @@ -130,6 +130,10 @@ New features SortedSetDocValues to allow filtering their TermsEnums with a CompiledAutomaton (Alan Woodward, Mike McCandless) +* LUCENE-7628: Scorer now has a getMatchingChildren() method that will + return all child scorers positioned on the current document. (Alan + Woodward) + Bug Fixes * LUCENE-7547: JapaneseTokenizerFactory was failing to close the diff --git a/lucene/core/src/java/org/apache/lucene/search/DisjunctionScorer.java b/lucene/core/src/java/org/apache/lucene/search/DisjunctionScorer.java index c53942a71c1..a76999e5e67 100644 --- a/lucene/core/src/java/org/apache/lucene/search/DisjunctionScorer.java +++ b/lucene/core/src/java/org/apache/lucene/search/DisjunctionScorer.java @@ -202,4 +202,12 @@ abstract class DisjunctionScorer extends Scorer { return children; } + @Override + public Collection getMatchingChildren() throws IOException { + List children = new ArrayList<>(); + for (DisiWrapper w = getSubMatches(); w != null; w = w.next) { + children.add(new ChildScorer(w.scorer, "SHOULD")); + } + return children; + } } diff --git a/lucene/core/src/java/org/apache/lucene/search/MinShouldMatchSumScorer.java b/lucene/core/src/java/org/apache/lucene/search/MinShouldMatchSumScorer.java index 032b5fef93e..b977400d9e1 100644 --- a/lucene/core/src/java/org/apache/lucene/search/MinShouldMatchSumScorer.java +++ b/lucene/core/src/java/org/apache/lucene/search/MinShouldMatchSumScorer.java @@ -132,6 +132,15 @@ final class MinShouldMatchSumScorer extends Scorer { return childScorers; } + @Override + public Collection getMatchingChildren() throws IOException { + List children = new ArrayList<>(); + for (DisiWrapper s = lead; s != null; s = s.next) { + children.add(new ChildScorer(s.scorer, "SHOULD")); + } + return children; + } + @Override public DocIdSetIterator iterator() { return new DocIdSetIterator() { diff --git a/lucene/core/src/java/org/apache/lucene/search/Scorer.java b/lucene/core/src/java/org/apache/lucene/search/Scorer.java index f43432777fe..2e35e91873e 100644 --- a/lucene/core/src/java/org/apache/lucene/search/Scorer.java +++ b/lucene/core/src/java/org/apache/lucene/search/Scorer.java @@ -82,6 +82,14 @@ public abstract class Scorer { public Collection getChildren() { return Collections.emptyList(); } + + /** + * Returns child sub-scorers that match the current document + * @lucene.experimental + */ + public Collection getMatchingChildren() throws IOException { + return getChildren(); + } /** A child Scorer and its relationship to its parent. * the meaning of the relationship depends upon the parent query. diff --git a/lucene/core/src/test/org/apache/lucene/search/TestBooleanQueryVisitSubscorers.java b/lucene/core/src/test/org/apache/lucene/search/TestBooleanQueryVisitSubscorers.java index 60ba528f89c..0909d5df42a 100644 --- a/lucene/core/src/test/org/apache/lucene/search/TestBooleanQueryVisitSubscorers.java +++ b/lucene/core/src/test/org/apache/lucene/search/TestBooleanQueryVisitSubscorers.java @@ -108,6 +108,39 @@ public class TestBooleanQueryVisitSubscorers extends LuceneTestCase { assertEquals(2, tfs.get(1).intValue()); // f2:search + f2:lucene assertEquals(2, tfs.get(2).intValue()); // f2:search + f2:lucene } + + public void testDisjunctionMatches() throws IOException { + BooleanQuery.Builder bq1 = new BooleanQuery.Builder(); + bq1.add(new TermQuery(new Term(F1, "lucene")), Occur.SHOULD); + bq1.add(new PhraseQuery(F2, "search", "engine"), Occur.SHOULD); + + Weight w1 = scorerSearcher.createNormalizedWeight(bq1.build(), true); + Scorer s1 = w1.scorer(reader.leaves().get(0)); + assertEquals(0, s1.iterator().nextDoc()); + assertEquals(2, s1.getMatchingChildren().size()); + + BooleanQuery.Builder bq2 = new BooleanQuery.Builder(); + bq2.add(new TermQuery(new Term(F1, "lucene")), Occur.SHOULD); + bq2.add(new PhraseQuery(F2, "search", "library"), Occur.SHOULD); + + Weight w2 = scorerSearcher.createNormalizedWeight(bq2.build(), true); + Scorer s2 = w2.scorer(reader.leaves().get(0)); + assertEquals(0, s2.iterator().nextDoc()); + assertEquals(1, s2.getMatchingChildren().size()); + } + + public void testMinShouldMatchMatches() throws IOException { + BooleanQuery.Builder bq = new BooleanQuery.Builder(); + bq.add(new TermQuery(new Term(F1, "lucene")), Occur.SHOULD); + bq.add(new TermQuery(new Term(F2, "lucene")), Occur.SHOULD); + bq.add(new PhraseQuery(F2, "search", "library"), Occur.SHOULD); + bq.setMinimumNumberShouldMatch(2); + + Weight w = scorerSearcher.createNormalizedWeight(bq.build(), true); + Scorer s = w.scorer(reader.leaves().get(0)); + assertEquals(0, s.iterator().nextDoc()); + assertEquals(2, s.getMatchingChildren().size()); + } public void testConjunctions() throws IOException { BooleanQuery.Builder bq = new BooleanQuery.Builder();