/* * 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; using Lucene.Net.Index; using IndexReader = Lucene.Net.Index.IndexReader; using ToStringUtils = Lucene.Net.Util.ToStringUtils; namespace Lucene.Net.Search { /// A query that applies a filter to the results of another query. /// ///

Note: the bits are retrieved from the filter each time this /// query is used in a search - use a CachingWrapperFilter to avoid /// regenerating the bits every time. /// ///

Created: Apr 20, 2004 8:58:29 AM /// ///

/// 1.4 /// [Serializable] public class FilteredQuery:Query { [Serializable] private class AnonymousClassWeight:Weight { public AnonymousClassWeight(Lucene.Net.Search.Weight weight, Lucene.Net.Search.Similarity similarity, FilteredQuery enclosingInstance) { InitBlock(weight, similarity, enclosingInstance); } private class AnonymousClassScorer:Scorer { private void InitBlock(Lucene.Net.Search.Scorer scorer, Lucene.Net.Search.DocIdSetIterator docIdSetIterator, AnonymousClassWeight enclosingInstance) { this.scorer = scorer; this.docIdSetIterator = docIdSetIterator; this.enclosingInstance = enclosingInstance; } private Lucene.Net.Search.Scorer scorer; private Lucene.Net.Search.DocIdSetIterator docIdSetIterator; private AnonymousClassWeight enclosingInstance; public AnonymousClassWeight Enclosing_Instance { get { return enclosingInstance; } } internal AnonymousClassScorer(Lucene.Net.Search.Scorer scorer, Lucene.Net.Search.DocIdSetIterator docIdSetIterator, AnonymousClassWeight enclosingInstance, Lucene.Net.Search.Similarity Param1):base(Param1) { InitBlock(scorer, docIdSetIterator, enclosingInstance); } private int doc = - 1; private int AdvanceToCommon(int scorerDoc, int disiDoc) { while (scorerDoc != disiDoc) { if (scorerDoc < disiDoc) { scorerDoc = scorer.Advance(disiDoc); } else { disiDoc = docIdSetIterator.Advance(scorerDoc); } } return scorerDoc; } public override int NextDoc() { int scorerDoc, disiDoc; return doc = (disiDoc = docIdSetIterator.NextDoc()) != NO_MORE_DOCS && (scorerDoc = scorer.NextDoc()) != NO_MORE_DOCS && AdvanceToCommon(scorerDoc, disiDoc) != NO_MORE_DOCS?scorer.DocID():NO_MORE_DOCS; } public override int DocID() { return doc; } public override int Advance(int target) { int disiDoc, scorerDoc; return doc = (disiDoc = docIdSetIterator.Advance(target)) != NO_MORE_DOCS && (scorerDoc = scorer.Advance(disiDoc)) != NO_MORE_DOCS && AdvanceToCommon(scorerDoc, disiDoc) != NO_MORE_DOCS?scorer.DocID():NO_MORE_DOCS; } public override float Score() { return Enclosing_Instance.Enclosing_Instance.Boost * scorer.Score(); } } private void InitBlock(Lucene.Net.Search.Weight weight, Lucene.Net.Search.Similarity similarity, FilteredQuery enclosingInstance) { this.weight = weight; this.similarity = similarity; this.enclosingInstance = enclosingInstance; } private Lucene.Net.Search.Weight weight; private Lucene.Net.Search.Similarity similarity; private FilteredQuery enclosingInstance; public FilteredQuery Enclosing_Instance { get { return enclosingInstance; } } private float value_Renamed; // pass these methods through to enclosed query's weight public override float Value { get { return value_Renamed; } } public override float GetSumOfSquaredWeights() { return weight.GetSumOfSquaredWeights()*Enclosing_Instance.Boost*Enclosing_Instance.Boost; } public override void Normalize(float v) { weight.Normalize(v); value_Renamed = weight.Value * Enclosing_Instance.Boost; } public override Explanation Explain(IndexReader ir, int i) { Explanation inner = weight.Explain(ir, i); if (Enclosing_Instance.Boost != 1) { Explanation preBoost = inner; inner = new Explanation(inner.Value * Enclosing_Instance.Boost, "product of:"); inner.AddDetail(new Explanation(Enclosing_Instance.Boost, "boost")); inner.AddDetail(preBoost); } Filter f = Enclosing_Instance.filter; DocIdSet docIdSet = f.GetDocIdSet(ir); DocIdSetIterator docIdSetIterator = docIdSet == null?DocIdSet.EMPTY_DOCIDSET.Iterator():docIdSet.Iterator(); if (docIdSetIterator == null) { docIdSetIterator = DocIdSet.EMPTY_DOCIDSET.Iterator(); } if (docIdSetIterator.Advance(i) == i) { return inner; } else { Explanation result = new Explanation(0.0f, "failure to match filter: " + f.ToString()); result.AddDetail(inner); return result; } } // return this query public override Query Query { get { return Enclosing_Instance; } } // return a filtering scorer public override Scorer Scorer(IndexReader indexReader, bool scoreDocsInOrder, bool topScorer) { Scorer scorer = weight.Scorer(indexReader, true, false); if (scorer == null) { return null; } DocIdSet docIdSet = Enclosing_Instance.filter.GetDocIdSet(indexReader); if (docIdSet == null) { return null; } DocIdSetIterator docIdSetIterator = docIdSet.Iterator(); if (docIdSetIterator == null) { return null; } return new AnonymousClassScorer(scorer, docIdSetIterator, this, similarity); } } internal Query query; internal Filter filter; /// Constructs a new query which applies a filter to the results of the original query. /// Filter.getDocIdSet() will be called every time this query is used in a search. /// /// Query to be filtered, cannot be null. /// /// Filter to apply to query results, cannot be null. /// public FilteredQuery(Query query, Filter filter) { this.query = query; this.filter = filter; } /// Returns a Weight that applies the filter to the enclosed query's Weight. /// This is accomplished by overriding the Scorer returned by the Weight. /// public override Weight CreateWeight(Searcher searcher) { Weight weight = query.CreateWeight(searcher); Similarity similarity = query.GetSimilarity(searcher); return new AnonymousClassWeight(weight, similarity, this); } /// Rewrites the wrapped query. public override Query Rewrite(IndexReader reader) { Query rewritten = query.Rewrite(reader); if (rewritten != query) { FilteredQuery clone = (FilteredQuery) this.Clone(); clone.query = rewritten; return clone; } else { return this; } } public virtual Query Query { get { return query; } } public virtual Filter Filter { get { return filter; } } // inherit javadoc public override void ExtractTerms(System.Collections.Generic.ISet terms) { Query.ExtractTerms(terms); } /// Prints a user-readable version of this query. public override System.String ToString(System.String s) { System.Text.StringBuilder buffer = new System.Text.StringBuilder(); buffer.Append("filtered("); buffer.Append(query.ToString(s)); buffer.Append(")->"); buffer.Append(filter); buffer.Append(ToStringUtils.Boost(Boost)); return buffer.ToString(); } /// Returns true iff o is equal to this. public override bool Equals(System.Object o) { if (o is FilteredQuery) { FilteredQuery fq = (FilteredQuery) o; return (query.Equals(fq.query) && filter.Equals(fq.filter) && Boost == fq.Boost); } return false; } /// Returns a hash code value for this object. public override int GetHashCode() { return query.GetHashCode() ^ filter.GetHashCode() + System.Convert.ToInt32(Boost); } } }