public abstract Query Rewrite(Query query);
/// <summary>Search implementation with arbitrary sorting. Finds /// the top <c>n</c> hits for <c>query</c>, applying /// <c>filter</c> if non-null, and sorting the hits by the criteria in /// <c>sort</c>. /// /// <p/>NOTE: this does not compute scores by default; use /// <see cref="IndexSearcher.SetDefaultFieldSortScoring(bool,bool)" /> to enable scoring. /// /// </summary> /// <throws> BooleanQuery.TooManyClauses </throws> public virtual TopFieldDocs Search(Query query, Filter filter, int n, Sort sort) { return Search(CreateWeight(query), filter, n, sort); }
/// <summary> Builds a new BooleanClause instance</summary> /// <param name="q">sub query /// </param> /// <param name="occur">how this clause should occur when matching documents /// </param> /// <returns> new BooleanClause instance /// </returns> protected internal virtual BooleanClause NewBooleanClause(Query q, Occur occur) { return new BooleanClause(q, occur); }
/// <summary> creates a weight for <c>query</c></summary> /// <returns> new weight /// </returns> public /*protected internal*/ virtual Weight CreateWeight(Query query) { return query.Weight(this); }
internal bool BufferDeleteQueries(Query[] queries) { lock (this) { WaitReady(null); for (int i = 0; i < queries.Length; i++) AddDeleteQuery(queries[i], numDocsInRAM); return TimeToFlushDeletes(); } }
private void AddDeleteQuery(Query query, int docID) { lock (this) { deletesInRAM.queries[query] = flushedDocCount + docID; deletesInRAM.AddBytesUsed(BYTES_PER_DEL_QUERY); } }
/// <summary>Constructs a filter which only matches documents matching /// <c>query</c>. /// </summary> public QueryWrapperFilter(Query query) { this.query = query; }
/// <summary> 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. /// </summary> /// <param name="query"> Query to be filtered, cannot be <c>null</c>. /// </param> /// <param name="filter">Filter to apply to query results, cannot be <c>null</c>. /// </param> public FilteredQuery(Query query, Filter filter) { this.query = query; this.filter = filter; }
/// <summary>Constructs a BooleanClause.</summary> public BooleanClause(Query query, Occur occur) { this._query = query; this.occur = occur; }
/// <summary>Expert: called when re-writing queries under MultiSearcher. /// /// Create a single query suitable for use by all subsearchers (in 1-1 /// correspondence with queries). This is an optimization of the OR of /// all queries. We handle the common optimization cases of equal /// queries and overlapping clauses of boolean OR queries (as generated /// by MultiTermQuery.rewrite()). /// Be careful overriding this method as queries[0] determines which /// method will be called and is not necessarily of the same type as /// the other queries. /// </summary> public virtual Query Combine(Query[] queries) { var uniques = new System.Collections.Generic.HashSet<Query>(); for (int i = 0; i < queries.Length; i++) { Query query = queries[i]; BooleanClause[] clauses = null; // check if we can split the query into clauses bool splittable = (query is BooleanQuery); if (splittable) { BooleanQuery bq = (BooleanQuery) query; splittable = bq.IsCoordDisabled(); clauses = bq.GetClauses(); for (int j = 0; splittable && j < clauses.Length; j++) { splittable = (clauses[j].Occur == Occur.SHOULD); } } if (splittable) { for (int j = 0; j < clauses.Length; j++) { uniques.Add(clauses[j].Query); } } else { uniques.Add(query); } } // optimization: if we have just one query, just return it if (uniques.Count == 1) { return uniques.First(); } BooleanQuery result = new BooleanQuery(true); foreach (Query key in uniques) { result.Add(key, Occur.SHOULD); } return result; }
/// <summary> Create weight in multiple index scenario. /// /// Distributed query processing is done in the following steps: /// 1. rewrite query /// 2. extract necessary terms /// 3. collect dfs for these terms from the Searchables /// 4. create query weight using aggregate dfs. /// 5. distribute that weight to Searchables /// 6. merge results /// /// Steps 1-4 are done here, 5+6 in the search() methods /// /// </summary> /// <returns> rewritten queries /// </returns> public /*protected internal*/ override Weight CreateWeight(Query original) { // step 1 Query rewrittenQuery = Rewrite(original); // step 2 ISet<Term> terms = Lucene.Net.Support.Compatibility.SetFactory.CreateHashSet<Term>(); rewrittenQuery.ExtractTerms(terms); // step3 Term[] allTermsArray = terms.ToArray(); int[] aggregatedDfs = new int[terms.Count]; for (int i = 0; i < searchables.Length; i++) { int[] dfs = searchables[i].DocFreqs(allTermsArray); for (int j = 0; j < aggregatedDfs.Length; j++) { aggregatedDfs[j] += dfs[j]; } } var dfMap = new Dictionary<Term, int>(); for (int i = 0; i < allTermsArray.Length; i++) { dfMap[allTermsArray[i]] = aggregatedDfs[i]; } // step4 int numDocs = MaxDoc; CachedDfSource cacheSim = new CachedDfSource(dfMap, numDocs, Similarity); return rewrittenQuery.Weight(cacheSim); }
public override Query Rewrite(Query original) { Query[] queries = new Query[searchables.Length]; for (int i = 0; i < searchables.Length; i++) { queries[i] = searchables[i].Rewrite(original); } return queries[0].Combine(queries); }
public override Query Rewrite(Query query) { // this is a bit of a hack. We know that a query which // creates a Weight based on this Dummy-Searcher is // always already rewritten (see preparedWeight()). // Therefore we just return the unmodified query here return query; }
/// <summary>Lower-level search API. /// /// <p/><see cref="Collector.Collect(int)" /> is called for every matching document. /// /// <p/>Applications should only use this if they need <i>all</i> of the matching /// documents. The high-level search API (<see cref="Searcher.Search(Query, int)" /> /// ) is usually more efficient, as it skips non-high-scoring hits. /// <p/>Note: The <c>score</c> passed to this method is a raw score. /// In other words, the score will not necessarily be a float whose value is /// between 0 and 1. /// </summary> /// <throws> BooleanQuery.TooManyClauses </throws> public virtual void Search(Query query, Collector results) { Search(CreateWeight(query), null, results); }
public override Query Rewrite(Query original) { Query query = original; for (Query rewrittenQuery = query.Rewrite(reader); rewrittenQuery != query; rewrittenQuery = query.Rewrite(reader)) { query = rewrittenQuery; } return query; }
/// <summary>Lower-level search API. /// /// <p/><see cref="Collector.Collect(int)" /> is called for every matching /// document. /// <br/>Collector-based access to remote indexes is discouraged. /// /// <p/>Applications should only use this if they need <i>all</i> of the /// matching documents. The high-level search API (<see cref="Searcher.Search(Query, Filter, int)" />) /// is usually more efficient, as it skips /// non-high-scoring hits. /// /// </summary> /// <param name="query">to match documents /// </param> /// <param name="filter">if non-null, used to permit documents to be collected. /// </param> /// <param name="results">to receive hits /// </param> /// <throws> BooleanQuery.TooManyClauses </throws> public virtual void Search(Query query, Filter filter, Collector results) { Search(CreateWeight(query), filter, results); }
/// <summary>Finds the top <c>n</c> /// hits for <c>query</c>, applying <c>filter</c> if non-null. /// /// </summary> /// <throws> BooleanQuery.TooManyClauses </throws> public virtual TopDocs Search(Query query, Filter filter, int n) { return Search(CreateWeight(query), filter, n); }
private void ApplySlop(Query q, int slop) { if (q is PhraseQuery) { ((PhraseQuery)q).Slop = slop; } else if (q is MultiPhraseQuery) { ((MultiPhraseQuery)q).Slop = slop; } }
/// <summary>Finds the top <c>n</c> /// hits for <c>query</c>. /// /// </summary> /// <throws> BooleanQuery.TooManyClauses </throws> public virtual TopDocs Search(Query query, int n) { return Search(query, null, n); }
internal bool BufferDeleteQuery(Query query) { lock (this) { WaitReady(null); AddDeleteQuery(query, numDocsInRAM); return TimeToFlushDeletes(); } }
/// <summary>Returns an Explanation that describes how <c>doc</c> scored against /// <c>query</c>. /// /// <p/>This is intended to be used in developing Similarity implementations, /// and, for good performance, should not be displayed with every hit. /// Computing an explanation is as expensive as executing the query over the /// entire index. /// </summary> public virtual Explanation Explain(Query query, int doc) { return Explain(CreateWeight(query), doc); }
/// <summary> Deletes the document(s) matching the provided query. /// /// <p/><b>NOTE</b>: if this method hits an OutOfMemoryError /// you should immediately close the writer. See <a /// href="#OOME">above</a> for details.<p/> /// /// </summary> /// <param name="query">the query to identify the documents to be deleted /// </param> /// <throws> CorruptIndexException if the index is corrupt </throws> /// <throws> IOException if there is a low-level IO error </throws> public virtual void DeleteDocuments(Query query) { EnsureOpen(); bool doFlush = docWriter.BufferDeleteQuery(query); if (doFlush) Flush(true, false, false); }
protected internal virtual void AddClause(List<BooleanClause> clauses, int conj, int mods, Query q) { bool required, prohibited; // If this term is introduced by AND, make the preceding term required, // unless it's already prohibited if (clauses.Count > 0 && conj == CONJ_AND) { BooleanClause c = clauses[clauses.Count - 1]; if (!c.IsProhibited) c.Occur = Occur.MUST; } if (clauses.Count > 0 && operator_Renamed == AND_OPERATOR && conj == CONJ_OR) { // If this term is introduced by OR, make the preceding term optional, // unless it's prohibited (that means we leave -a OR b but +a OR b-->a OR b) // notice if the input is a OR b, first term is parsed as required; without // this modification a OR b would parsed as +a OR b BooleanClause c = clauses[clauses.Count - 1]; if (!c.IsProhibited) c.Occur = Occur.SHOULD; } // We might have been passed a null query; the term might have been // filtered away by the analyzer. if (q == null) return; if (operator_Renamed == OR_OPERATOR) { // We set REQUIRED if we're introduced by AND or +; PROHIBITED if // introduced by NOT or -; make sure not to set both. prohibited = (mods == MOD_NOT); required = (mods == MOD_REQ); if (conj == CONJ_AND && !prohibited) { required = true; } } else { // We set PROHIBITED if we're introduced by NOT or -; We set REQUIRED // if not PROHIBITED and not introduced by OR prohibited = (mods == MOD_NOT); required = (!prohibited && conj != CONJ_OR); } if (required && !prohibited) clauses.Add(NewBooleanClause(q, Occur.MUST)); else if (!required && !prohibited) clauses.Add(NewBooleanClause(q, Occur.SHOULD)); else if (!required && prohibited) clauses.Add(NewBooleanClause(q, Occur.MUST_NOT)); else throw new SystemException("Clause cannot be both required and prohibited"); }