Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/Lucene.Net.Light.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/Search/BooleanScorer2.cs')
-rw-r--r--src/core/Search/BooleanScorer2.cs417
1 files changed, 417 insertions, 0 deletions
diff --git a/src/core/Search/BooleanScorer2.cs b/src/core/Search/BooleanScorer2.cs
new file mode 100644
index 0000000..3c8c611
--- /dev/null
+++ b/src/core/Search/BooleanScorer2.cs
@@ -0,0 +1,417 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+
+namespace Lucene.Net.Search
+{
+
+ /* See the description in BooleanScorer.java, comparing
+ * BooleanScorer & BooleanScorer2 */
+
+ /// <summary>An alternative to BooleanScorer that also allows a minimum number
+ /// of optional scorers that should match.
+ /// <br/>Implements skipTo(), and has no limitations on the numbers of added scorers.
+ /// <br/>Uses ConjunctionScorer, DisjunctionScorer, ReqOptScorer and ReqExclScorer.
+ /// </summary>
+ class BooleanScorer2 : Scorer
+ {
+ private class AnonymousClassDisjunctionSumScorer:DisjunctionSumScorer
+ {
+ private void InitBlock(BooleanScorer2 enclosingInstance)
+ {
+ this.enclosingInstance = enclosingInstance;
+ }
+ private BooleanScorer2 enclosingInstance;
+ public BooleanScorer2 Enclosing_Instance
+ {
+ get
+ {
+ return enclosingInstance;
+ }
+
+ }
+ internal AnonymousClassDisjunctionSumScorer(BooleanScorer2 enclosingInstance, System.Collections.Generic.IList<Scorer> scorers, int minNrShouldMatch)
+ : base(scorers, minNrShouldMatch)
+ {
+ InitBlock(enclosingInstance);
+ }
+ private int lastScoredDoc = - 1;
+ // Save the score of lastScoredDoc, so that we don't compute it more than
+ // once in score().
+ private float lastDocScore = System.Single.NaN;
+ public override float Score()
+ {
+ int doc = DocID();
+ if (doc >= lastScoredDoc)
+ {
+ if (doc > lastScoredDoc)
+ {
+ lastDocScore = base.Score();
+ lastScoredDoc = doc;
+ }
+ Enclosing_Instance.coordinator.nrMatchers += base.nrMatchers;
+ }
+ return lastDocScore;
+ }
+ }
+ private class AnonymousClassConjunctionScorer:ConjunctionScorer
+ {
+ private void InitBlock(int requiredNrMatchers, BooleanScorer2 enclosingInstance)
+ {
+ this.requiredNrMatchers = requiredNrMatchers;
+ this.enclosingInstance = enclosingInstance;
+ }
+ private int requiredNrMatchers;
+ private BooleanScorer2 enclosingInstance;
+ public BooleanScorer2 Enclosing_Instance
+ {
+ get
+ {
+ return enclosingInstance;
+ }
+
+ }
+ internal AnonymousClassConjunctionScorer(int requiredNrMatchers, BooleanScorer2 enclosingInstance, Lucene.Net.Search.Similarity defaultSimilarity, System.Collections.Generic.IList<Scorer> requiredScorers)
+ : base(defaultSimilarity, requiredScorers)
+ {
+ InitBlock(requiredNrMatchers, enclosingInstance);
+ }
+ private int lastScoredDoc = - 1;
+ // Save the score of lastScoredDoc, so that we don't compute it more than
+ // once in score().
+ private float lastDocScore = System.Single.NaN;
+ public override float Score()
+ {
+ int doc = DocID();
+ if (doc >= lastScoredDoc)
+ {
+ if (doc > lastScoredDoc)
+ {
+ lastDocScore = base.Score();
+ lastScoredDoc = doc;
+ }
+ Enclosing_Instance.coordinator.nrMatchers += requiredNrMatchers;
+ }
+ // All scorers match, so defaultSimilarity super.score() always has 1 as
+ // the coordination factor.
+ // Therefore the sum of the scores of the requiredScorers
+ // is used as score.
+ return lastDocScore;
+ }
+ }
+
+ private System.Collections.Generic.List<Scorer> requiredScorers;
+ private System.Collections.Generic.List<Scorer> optionalScorers;
+ private System.Collections.Generic.List<Scorer> prohibitedScorers;
+
+ private class Coordinator
+ {
+ public Coordinator(BooleanScorer2 enclosingInstance)
+ {
+ InitBlock(enclosingInstance);
+ }
+ private void InitBlock(BooleanScorer2 enclosingInstance)
+ {
+ this.enclosingInstance = enclosingInstance;
+ }
+ private BooleanScorer2 enclosingInstance;
+ public BooleanScorer2 Enclosing_Instance
+ {
+ get
+ {
+ return enclosingInstance;
+ }
+
+ }
+ internal float[] coordFactors = null;
+ internal int maxCoord = 0; // to be increased for each non prohibited scorer
+ internal int nrMatchers; // to be increased by score() of match counting scorers.
+
+ internal virtual void Init()
+ {
+ // use after all scorers have been added.
+ coordFactors = new float[maxCoord + 1];
+ Similarity sim = Enclosing_Instance.Similarity;
+ for (int i = 0; i <= maxCoord; i++)
+ {
+ coordFactors[i] = sim.Coord(i, maxCoord);
+ }
+ }
+ }
+
+ private Coordinator coordinator;
+
+ /// <summary>The scorer to which all scoring will be delegated,
+ /// except for computing and using the coordination factor.
+ /// </summary>
+ private Scorer countingSumScorer;
+
+ /// <summary>The number of optionalScorers that need to match (if there are any) </summary>
+ private int minNrShouldMatch;
+
+ private int doc = - 1;
+
+ /// <summary> Creates a <see cref="Scorer" /> with the given similarity and lists of required,
+ /// prohibited and optional scorers. In no required scorers are added, at least
+ /// one of the optional scorers will have to match during the search.
+ ///
+ /// </summary>
+ /// <param name="similarity">The similarity to be used.
+ /// </param>
+ /// <param name="minNrShouldMatch">The minimum number of optional added scorers that should match
+ /// during the search. In case no required scorers are added, at least
+ /// one of the optional scorers will have to match during the search.
+ /// </param>
+ /// <param name="required">the list of required scorers.
+ /// </param>
+ /// <param name="prohibited">the list of prohibited scorers.
+ /// </param>
+ /// <param name="optional">the list of optional scorers.
+ /// </param>
+ public BooleanScorer2(Similarity similarity, int minNrShouldMatch,
+ System.Collections.Generic.List<Scorer> required,
+ System.Collections.Generic.List<Scorer> prohibited,
+ System.Collections.Generic.List<Scorer> optional)
+ : base(similarity)
+ {
+ if (minNrShouldMatch < 0)
+ {
+ throw new System.ArgumentException("Minimum number of optional scorers should not be negative");
+ }
+ coordinator = new Coordinator(this);
+ this.minNrShouldMatch = minNrShouldMatch;
+
+ optionalScorers = optional;
+ coordinator.maxCoord += optional.Count;
+
+ requiredScorers = required;
+ coordinator.maxCoord += required.Count;
+
+ prohibitedScorers = prohibited;
+
+ coordinator.Init();
+ countingSumScorer = MakeCountingSumScorer();
+ }
+
+ /// <summary>Count a scorer as a single match. </summary>
+ private class SingleMatchScorer:Scorer
+ {
+ private void InitBlock(BooleanScorer2 enclosingInstance)
+ {
+ this.enclosingInstance = enclosingInstance;
+ }
+ private BooleanScorer2 enclosingInstance;
+ public BooleanScorer2 Enclosing_Instance
+ {
+ get
+ {
+ return enclosingInstance;
+ }
+
+ }
+ private Scorer scorer;
+ private int lastScoredDoc = - 1;
+ // Save the score of lastScoredDoc, so that we don't compute it more than
+ // once in score().
+ private float lastDocScore = System.Single.NaN;
+
+ internal SingleMatchScorer(BooleanScorer2 enclosingInstance, Scorer scorer):base(scorer.Similarity)
+ {
+ InitBlock(enclosingInstance);
+ this.scorer = scorer;
+ }
+ public override float Score()
+ {
+ int doc = DocID();
+ if (doc >= lastScoredDoc)
+ {
+ if (doc > lastScoredDoc)
+ {
+ lastDocScore = scorer.Score();
+ lastScoredDoc = doc;
+ }
+ Enclosing_Instance.coordinator.nrMatchers++;
+ }
+ return lastDocScore;
+ }
+
+ public override int DocID()
+ {
+ return scorer.DocID();
+ }
+
+ public override int NextDoc()
+ {
+ return scorer.NextDoc();
+ }
+
+ public override int Advance(int target)
+ {
+ return scorer.Advance(target);
+ }
+ }
+
+ private Scorer CountingDisjunctionSumScorer(System.Collections.Generic.List<Scorer> scorers, int minNrShouldMatch)
+ {
+ // each scorer from the list counted as a single matcher
+ return new AnonymousClassDisjunctionSumScorer(this, scorers, minNrShouldMatch);
+ }
+
+ private static readonly Similarity defaultSimilarity;
+
+ private Scorer CountingConjunctionSumScorer(System.Collections.Generic.List<Scorer> requiredScorers)
+ {
+ // each scorer from the list counted as a single matcher
+ int requiredNrMatchers = requiredScorers.Count;
+ return new AnonymousClassConjunctionScorer(requiredNrMatchers, this, defaultSimilarity, requiredScorers);
+ }
+
+ private Scorer DualConjunctionSumScorer(Scorer req1, Scorer req2)
+ {
+ // non counting.
+ return new ConjunctionScorer(defaultSimilarity, new Scorer[]{req1, req2});
+ // All scorers match, so defaultSimilarity always has 1 as
+ // the coordination factor.
+ // Therefore the sum of the scores of two scorers
+ // is used as score.
+ }
+
+ /// <summary>Returns the scorer to be used for match counting and score summing.
+ /// Uses requiredScorers, optionalScorers and prohibitedScorers.
+ /// </summary>
+ private Scorer MakeCountingSumScorer()
+ {
+ // each scorer counted as a single matcher
+ return (requiredScorers.Count == 0)?MakeCountingSumScorerNoReq():MakeCountingSumScorerSomeReq();
+ }
+
+ private Scorer MakeCountingSumScorerNoReq()
+ {
+ // No required scorers
+ // minNrShouldMatch optional scorers are required, but at least 1
+ int nrOptRequired = (minNrShouldMatch < 1)?1:minNrShouldMatch;
+ Scorer requiredCountingSumScorer;
+ if (optionalScorers.Count > nrOptRequired)
+ requiredCountingSumScorer = CountingDisjunctionSumScorer(optionalScorers, nrOptRequired);
+ else if (optionalScorers.Count == 1)
+ requiredCountingSumScorer = new SingleMatchScorer(this, optionalScorers[0]);
+ else
+ requiredCountingSumScorer = CountingConjunctionSumScorer(optionalScorers);
+ return AddProhibitedScorers(requiredCountingSumScorer);
+ }
+
+ private Scorer MakeCountingSumScorerSomeReq()
+ {
+ // At least one required scorer.
+ if (optionalScorers.Count == minNrShouldMatch)
+ {
+ // all optional scorers also required.
+ var allReq = new System.Collections.Generic.List<Scorer>(requiredScorers);
+ allReq.AddRange(optionalScorers);
+ return AddProhibitedScorers(CountingConjunctionSumScorer(allReq));
+ }
+ else
+ {
+ // optionalScorers.size() > minNrShouldMatch, and at least one required scorer
+ Scorer requiredCountingSumScorer =
+ requiredScorers.Count == 1
+ ? new SingleMatchScorer(this, requiredScorers[0])
+ : CountingConjunctionSumScorer(requiredScorers);
+ if (minNrShouldMatch > 0)
+ {
+ // use a required disjunction scorer over the optional scorers
+ return AddProhibitedScorers(DualConjunctionSumScorer(requiredCountingSumScorer, CountingDisjunctionSumScorer(optionalScorers, minNrShouldMatch)));
+ }
+ else
+ {
+ // minNrShouldMatch == 0
+ return new ReqOptSumScorer(AddProhibitedScorers(requiredCountingSumScorer),
+ optionalScorers.Count == 1
+ ? new SingleMatchScorer(this, optionalScorers[0])
+ : CountingDisjunctionSumScorer(optionalScorers, 1));
+ }
+ }
+ }
+
+ /// <summary>Returns the scorer to be used for match counting and score summing.
+ /// Uses the given required scorer and the prohibitedScorers.
+ /// </summary>
+ /// <param name="requiredCountingSumScorer">A required scorer already built.
+ /// </param>
+ private Scorer AddProhibitedScorers(Scorer requiredCountingSumScorer)
+ {
+ return (prohibitedScorers.Count == 0)
+ ? requiredCountingSumScorer
+ : new ReqExclScorer(requiredCountingSumScorer,
+ ((prohibitedScorers.Count == 1)
+ ? prohibitedScorers[0]
+ : new DisjunctionSumScorer(prohibitedScorers)));
+ }
+
+ /// <summary>Scores and collects all matching documents.</summary>
+ /// <param name="collector">The collector to which all matching documents are passed through.
+ /// </param>
+ public override void Score(Collector collector)
+ {
+ collector.SetScorer(this);
+ while ((doc = countingSumScorer.NextDoc()) != NO_MORE_DOCS)
+ {
+ collector.Collect(doc);
+ }
+ }
+
+ public /*protected internal*/ override bool Score(Collector collector, int max, int firstDocID)
+ {
+ doc = firstDocID;
+ collector.SetScorer(this);
+ while (doc < max)
+ {
+ collector.Collect(doc);
+ doc = countingSumScorer.NextDoc();
+ }
+ return doc != NO_MORE_DOCS;
+ }
+
+ public override int DocID()
+ {
+ return doc;
+ }
+
+ public override int NextDoc()
+ {
+ return doc = countingSumScorer.NextDoc();
+ }
+
+ public override float Score()
+ {
+ coordinator.nrMatchers = 0;
+ float sum = countingSumScorer.Score();
+ return sum * coordinator.coordFactors[coordinator.nrMatchers];
+ }
+
+ public override int Advance(int target)
+ {
+ return doc = countingSumScorer.Advance(target);
+ }
+
+ static BooleanScorer2()
+ {
+ defaultSimilarity = Search.Similarity.Default;
+ }
+ }
+} \ No newline at end of file