cvsimport
[beagle.git] / beagled / Lucene.Net / Search / PhrasePrefixQuery.cs
blob525e34760fdb4313cbf2ded208ff0bd4be3c574d
1 /*
2 * Copyright 2004 The Apache Software Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 using System;
18 using IndexReader = Lucene.Net.Index.IndexReader;
19 using MultipleTermPositions = Lucene.Net.Index.MultipleTermPositions;
20 using Term = Lucene.Net.Index.Term;
21 using TermPositions = Lucene.Net.Index.TermPositions;
22 using ToStringUtils = Lucene.Net.Util.ToStringUtils;
24 namespace Lucene.Net.Search
27 /// <summary> PhrasePrefixQuery is a generalized version of PhraseQuery, with an added
28 /// method {@link #Add(Term[])}.
29 /// To use this class, to search for the phrase "Microsoft app*" first use
30 /// add(Term) on the term "Microsoft", then find all terms that has "app" as
31 /// prefix using IndexReader.terms(Term), and use PhrasePrefixQuery.add(Term[]
32 /// terms) to add them to the query.
33 ///
34 /// </summary>
35 /// <deprecated> use {@link Lucene.Net.search.MultiPhraseQuery} instead
36 /// </deprecated>
37 /// <author> Anders Nielsen
38 /// </author>
39 /// <version> 1.0
40 /// </version>
41 [Serializable]
42 public class PhrasePrefixQuery : Query
44 private System.String field;
45 private System.Collections.ArrayList termArrays = new System.Collections.ArrayList();
46 private System.Collections.ArrayList positions = System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList(10));
48 private int slop = 0;
50 /// <summary>Sets the phrase slop for this query.</summary>
51 /// <seealso cref="PhraseQuery.SetSlop(int)">
52 /// </seealso>
53 public virtual void SetSlop(int s)
55 slop = s;
58 /// <summary>Sets the phrase slop for this query.</summary>
59 /// <seealso cref="PhraseQuery.GetSlop()">
60 /// </seealso>
61 public virtual int GetSlop()
63 return slop;
66 /// <summary>Add a single term at the next position in the phrase.</summary>
67 /// <seealso cref="PhraseQuery.Add(Term)">
68 /// </seealso>
69 public virtual void Add(Term term)
71 Add(new Term[]{term});
74 /// <summary>Add multiple terms at the next position in the phrase. Any of the terms
75 /// may match.
76 ///
77 /// </summary>
78 /// <seealso cref="PhraseQuery.Add(Term)">
79 /// </seealso>
80 public virtual void Add(Term[] terms)
82 int position = 0;
83 if (positions.Count > 0)
84 position = ((System.Int32) positions[positions.Count - 1]) + 1;
86 Add(terms, position);
89 /// <summary> Allows to specify the relative position of terms within the phrase.
90 ///
91 /// </summary>
92 /// <seealso cref="PhraseQuery.Add(Term, int)">
93 /// </seealso>
94 /// <param name="terms">
95 /// </param>
96 /// <param name="position">
97 /// </param>
98 public virtual void Add(Term[] terms, int position)
100 if (termArrays.Count == 0)
101 field = terms[0].Field();
103 for (int i = 0; i < terms.Length; i++)
105 if (terms[i].Field() != field)
107 throw new System.ArgumentException("All phrase terms must be in the same field (" + field + "): " + terms[i]);
111 termArrays.Add(terms);
112 positions.Add((System.Int32) position);
115 /// <summary> Returns the relative positions of terms in this phrase.</summary>
116 public virtual int[] GetPositions()
118 int[] result = new int[positions.Count];
119 for (int i = 0; i < positions.Count; i++)
120 result[i] = ((System.Int32) positions[i]);
121 return result;
124 [Serializable]
125 private class PhrasePrefixWeight : Weight
127 private void InitBlock(PhrasePrefixQuery enclosingInstance)
129 this.enclosingInstance = enclosingInstance;
131 private PhrasePrefixQuery enclosingInstance;
132 public PhrasePrefixQuery Enclosing_Instance
136 return enclosingInstance;
140 private Similarity similarity;
141 private float value_Renamed;
142 private float idf;
143 private float queryNorm;
144 private float queryWeight;
146 public PhrasePrefixWeight(PhrasePrefixQuery enclosingInstance, Searcher searcher)
148 InitBlock(enclosingInstance);
149 this.similarity = Enclosing_Instance.GetSimilarity(searcher);
151 // compute idf
152 System.Collections.IEnumerator i = Enclosing_Instance.termArrays.GetEnumerator();
153 while (i.MoveNext())
155 Term[] terms = (Term[]) i.Current;
156 for (int j = 0; j < terms.Length; j++)
158 idf += Enclosing_Instance.GetSimilarity(searcher).Idf(terms[j], searcher);
163 public virtual Query GetQuery()
165 return Enclosing_Instance;
167 public virtual float GetValue()
169 return value_Renamed;
172 public virtual float SumOfSquaredWeights()
174 queryWeight = idf * Enclosing_Instance.GetBoost(); // compute query weight
175 return queryWeight * queryWeight; // square it
178 public virtual void Normalize(float queryNorm)
180 this.queryNorm = queryNorm;
181 queryWeight *= queryNorm; // normalize query weight
182 value_Renamed = queryWeight * idf; // idf for document
185 public virtual Scorer Scorer(IndexReader reader)
187 if (Enclosing_Instance.termArrays.Count == 0)
188 // optimize zero-term case
189 return null;
191 TermPositions[] tps = new TermPositions[Enclosing_Instance.termArrays.Count];
192 for (int i = 0; i < tps.Length; i++)
194 Term[] terms = (Term[]) Enclosing_Instance.termArrays[i];
196 TermPositions p;
197 if (terms.Length > 1)
198 p = new MultipleTermPositions(reader, terms);
199 else
200 p = reader.TermPositions(terms[0]);
202 if (p == null)
203 return null;
205 tps[i] = p;
208 if (Enclosing_Instance.slop == 0)
209 return new ExactPhraseScorer(this, tps, Enclosing_Instance.GetPositions(), similarity, reader.Norms(Enclosing_Instance.field));
210 else
211 return new SloppyPhraseScorer(this, tps, Enclosing_Instance.GetPositions(), similarity, Enclosing_Instance.slop, reader.Norms(Enclosing_Instance.field));
214 public virtual Explanation Explain(IndexReader reader, int doc)
216 Explanation result = new Explanation();
217 result.SetDescription("weight(" + GetQuery() + " in " + doc + "), product of:");
219 Explanation idfExpl = new Explanation(idf, "idf(" + GetQuery() + ")");
221 // explain query weight
222 Explanation queryExpl = new Explanation();
223 queryExpl.SetDescription("queryWeight(" + GetQuery() + "), product of:");
225 Explanation boostExpl = new Explanation(Enclosing_Instance.GetBoost(), "boost");
226 if (Enclosing_Instance.GetBoost() != 1.0f)
227 queryExpl.AddDetail(boostExpl);
229 queryExpl.AddDetail(idfExpl);
231 Explanation queryNormExpl = new Explanation(queryNorm, "queryNorm");
232 queryExpl.AddDetail(queryNormExpl);
234 queryExpl.SetValue(boostExpl.GetValue() * idfExpl.GetValue() * queryNormExpl.GetValue());
236 result.AddDetail(queryExpl);
238 // explain field weight
239 Explanation fieldExpl = new Explanation();
240 fieldExpl.SetDescription("fieldWeight(" + GetQuery() + " in " + doc + "), product of:");
242 Explanation tfExpl = Scorer(reader).Explain(doc);
243 fieldExpl.AddDetail(tfExpl);
244 fieldExpl.AddDetail(idfExpl);
246 Explanation fieldNormExpl = new Explanation();
247 byte[] fieldNorms = reader.Norms(Enclosing_Instance.field);
248 float fieldNorm = fieldNorms != null?Similarity.DecodeNorm(fieldNorms[doc]):0.0f;
249 fieldNormExpl.SetValue(fieldNorm);
250 fieldNormExpl.SetDescription("fieldNorm(field=" + Enclosing_Instance.field + ", doc=" + doc + ")");
251 fieldExpl.AddDetail(fieldNormExpl);
253 fieldExpl.SetValue(tfExpl.GetValue() * idfExpl.GetValue() * fieldNormExpl.GetValue());
255 result.AddDetail(fieldExpl);
257 // combine them
258 result.SetValue(queryExpl.GetValue() * fieldExpl.GetValue());
260 if (queryExpl.GetValue() == 1.0f)
261 return fieldExpl;
263 return result;
267 protected internal override Weight CreateWeight(Searcher searcher)
269 if (termArrays.Count == 1)
271 // optimize one-term case
272 Term[] terms = (Term[]) termArrays[0];
273 BooleanQuery boq = new BooleanQuery(true);
274 for (int i = 0; i < terms.Length; i++)
276 boq.Add(new TermQuery(terms[i]), BooleanClause.Occur.SHOULD);
278 boq.SetBoost(GetBoost());
279 return boq.CreateWeight(searcher);
281 return new PhrasePrefixWeight(this, searcher);
284 /// <summary>Prints a user-readable version of this query. </summary>
285 public override System.String ToString(System.String f)
287 System.Text.StringBuilder buffer = new System.Text.StringBuilder();
288 if (!field.Equals(f))
290 buffer.Append(field);
291 buffer.Append(":");
294 buffer.Append("\"");
295 System.Collections.IEnumerator i = termArrays.GetEnumerator();
296 while (i.MoveNext())
298 Term[] terms = (Term[]) i.Current;
299 buffer.Append(terms[0].Text() + (terms.Length > 1?"*":""));
300 if (i.MoveNext())
301 buffer.Append(" ");
303 buffer.Append("\"");
305 if (slop != 0)
307 buffer.Append("~");
308 buffer.Append(slop);
311 buffer.Append(ToStringUtils.Boost(GetBoost()));
313 return buffer.ToString();