QueryResponses.cs, DumpIndex.cs, IQueryResult.cs, QueryExecutor.cs, QueryResult.cs...
[beagle.git] / beagled / Lucene.Net / Search / MultiPhraseQuery.cs
blobdd68bc1f697aee61973076444994e1e0d8f597d3
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> MultiPhraseQuery 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 have "app" as
31 /// prefix using IndexReader.terms(Term), and use MultiPhraseQuery.add(Term[]
32 /// terms) to add them to the query.
33 ///
34 /// </summary>
35 /// <author> Anders Nielsen
36 /// </author>
37 /// <version> 1.0
38 /// </version>
39 [Serializable]
40 public class MultiPhraseQuery : Query
42 private System.String field;
43 private System.Collections.ArrayList termArrays = new System.Collections.ArrayList();
44 private System.Collections.ArrayList positions = System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList(10));
46 private int slop = 0;
48 /// <summary>Sets the phrase slop for this query.</summary>
49 /// <seealso cref="PhraseQuery.SetSlop(int)">
50 /// </seealso>
51 public virtual void SetSlop(int s)
53 slop = s;
56 /// <summary>Sets the phrase slop for this query.</summary>
57 /// <seealso cref="PhraseQuery.GetSlop()">
58 /// </seealso>
59 public virtual int GetSlop()
61 return slop;
64 /// <summary>Add a single term at the next position in the phrase.</summary>
65 /// <seealso cref="PhraseQuery.Add(Term)">
66 /// </seealso>
67 public virtual void Add(Term term)
69 Add(new Term[]{term});
72 /// <summary>Add multiple terms at the next position in the phrase. Any of the terms
73 /// may match.
74 ///
75 /// </summary>
76 /// <seealso cref="PhraseQuery.Add(Term)">
77 /// </seealso>
78 public virtual void Add(Term[] terms)
80 int position = 0;
81 if (positions.Count > 0)
82 position = ((System.Int32) positions[positions.Count - 1]) + 1;
84 Add(terms, position);
87 /// <summary> Allows to specify the relative position of terms within the phrase.
88 ///
89 /// </summary>
90 /// <seealso cref="PhraseQuery.Add(Term, int)">
91 /// </seealso>
92 /// <param name="terms">
93 /// </param>
94 /// <param name="position">
95 /// </param>
96 public virtual void Add(Term[] terms, int position)
98 if (termArrays.Count == 0)
99 field = terms[0].Field();
101 for (int i = 0; i < terms.Length; i++)
103 if ((System.Object) terms[i].Field() != (System.Object) field)
105 throw new System.ArgumentException("All phrase terms must be in the same field (" + field + "): " + terms[i]);
109 termArrays.Add(terms);
110 positions.Add((System.Int32) position);
113 /// <summary> Returns the relative positions of terms in this phrase.</summary>
114 public virtual int[] GetPositions()
116 int[] result = new int[positions.Count];
117 for (int i = 0; i < positions.Count; i++)
118 result[i] = ((System.Int32) positions[i]);
119 return result;
122 [Serializable]
123 private class MultiPhraseWeight : Weight
125 private void InitBlock(MultiPhraseQuery enclosingInstance)
127 this.enclosingInstance = enclosingInstance;
129 private MultiPhraseQuery enclosingInstance;
130 public MultiPhraseQuery Enclosing_Instance
134 return enclosingInstance;
138 private Similarity similarity;
139 private float value_Renamed;
140 private float idf;
141 private float queryNorm;
142 private float queryWeight;
144 public MultiPhraseWeight(MultiPhraseQuery enclosingInstance, Searcher searcher)
146 InitBlock(enclosingInstance);
147 this.similarity = Enclosing_Instance.GetSimilarity(searcher);
149 // compute idf
150 System.Collections.IEnumerator i = Enclosing_Instance.termArrays.GetEnumerator();
151 while (i.MoveNext())
153 Term[] terms = (Term[]) i.Current;
154 for (int j = 0; j < terms.Length; j++)
156 idf += Enclosing_Instance.GetSimilarity(searcher).Idf(terms[j], searcher);
161 public virtual Query GetQuery()
163 return Enclosing_Instance;
165 public virtual float GetValue()
167 return value_Renamed;
170 public virtual float SumOfSquaredWeights()
172 queryWeight = idf * Enclosing_Instance.GetBoost(); // compute query weight
173 return queryWeight * queryWeight; // square it
176 public virtual void Normalize(float queryNorm)
178 this.queryNorm = queryNorm;
179 queryWeight *= queryNorm; // normalize query weight
180 value_Renamed = queryWeight * idf; // idf for document
183 public virtual Scorer Scorer(IndexReader reader)
185 if (Enclosing_Instance.termArrays.Count == 0)
186 // optimize zero-term case
187 return null;
189 TermPositions[] tps = new TermPositions[Enclosing_Instance.termArrays.Count];
190 for (int i = 0; i < tps.Length; i++)
192 Term[] terms = (Term[]) Enclosing_Instance.termArrays[i];
194 TermPositions p;
195 if (terms.Length > 1)
196 p = new MultipleTermPositions(reader, terms);
197 else
198 p = reader.TermPositions(terms[0]);
200 if (p == null)
201 return null;
203 tps[i] = p;
206 if (Enclosing_Instance.slop == 0)
207 return new ExactPhraseScorer(this, tps, Enclosing_Instance.GetPositions(), similarity, reader.Norms(Enclosing_Instance.field));
208 else
209 return new SloppyPhraseScorer(this, tps, Enclosing_Instance.GetPositions(), similarity, Enclosing_Instance.slop, reader.Norms(Enclosing_Instance.field));
212 public virtual Explanation Explain(IndexReader reader, int doc)
214 Explanation result = new Explanation();
215 result.SetDescription("weight(" + GetQuery() + " in " + doc + "), product of:");
217 Explanation idfExpl = new Explanation(idf, "idf(" + GetQuery() + ")");
219 // explain query weight
220 Explanation queryExpl = new Explanation();
221 queryExpl.SetDescription("queryWeight(" + GetQuery() + "), product of:");
223 Explanation boostExpl = new Explanation(Enclosing_Instance.GetBoost(), "boost");
224 if (Enclosing_Instance.GetBoost() != 1.0f)
225 queryExpl.AddDetail(boostExpl);
227 queryExpl.AddDetail(idfExpl);
229 Explanation queryNormExpl = new Explanation(queryNorm, "queryNorm");
230 queryExpl.AddDetail(queryNormExpl);
232 queryExpl.SetValue(boostExpl.GetValue() * idfExpl.GetValue() * queryNormExpl.GetValue());
234 result.AddDetail(queryExpl);
236 // explain field weight
237 Explanation fieldExpl = new Explanation();
238 fieldExpl.SetDescription("fieldWeight(" + GetQuery() + " in " + doc + "), product of:");
240 Explanation tfExpl = Scorer(reader).Explain(doc);
241 fieldExpl.AddDetail(tfExpl);
242 fieldExpl.AddDetail(idfExpl);
244 Explanation fieldNormExpl = new Explanation();
245 byte[] fieldNorms = reader.Norms(Enclosing_Instance.field);
246 float fieldNorm = fieldNorms != null ? Similarity.DecodeNorm(fieldNorms[doc]) : 0.0f;
247 fieldNormExpl.SetValue(fieldNorm);
248 fieldNormExpl.SetDescription("fieldNorm(field=" + Enclosing_Instance.field + ", doc=" + doc + ")");
249 fieldExpl.AddDetail(fieldNormExpl);
251 fieldExpl.SetValue(tfExpl.GetValue() * idfExpl.GetValue() * fieldNormExpl.GetValue());
253 result.AddDetail(fieldExpl);
255 // combine them
256 result.SetValue(queryExpl.GetValue() * fieldExpl.GetValue());
258 if (queryExpl.GetValue() == 1.0f)
259 return fieldExpl;
261 return result;
265 public override Query Rewrite(IndexReader reader)
267 if (termArrays.Count == 1)
269 // optimize one-term case
270 Term[] terms = (Term[]) termArrays[0];
271 BooleanQuery boq = new BooleanQuery(true);
272 for (int i = 0; i < terms.Length; i++)
274 boq.Add(new TermQuery(terms[i]), BooleanClause.Occur.SHOULD);
276 boq.SetBoost(GetBoost());
277 return boq;
279 else
281 return this;
285 protected internal override Weight CreateWeight(Searcher searcher)
287 return new MultiPhraseWeight(this, searcher);
290 /// <summary>Prints a user-readable version of this query. </summary>
291 public override System.String ToString(System.String f)
293 System.Text.StringBuilder buffer = new System.Text.StringBuilder();
294 if (!field.Equals(f))
296 buffer.Append(field);
297 buffer.Append(":");
300 bool appendSpace = false;
302 buffer.Append("\"");
303 System.Collections.IEnumerator i = termArrays.GetEnumerator();
304 while (i.MoveNext())
306 if (appendSpace == true)
307 buffer.Append(" ");
308 else
309 appendSpace = true;
311 Term[] terms = (Term[]) i.Current;
312 if (terms.Length > 1)
314 buffer.Append("(");
315 for (int j = 0; j < terms.Length; j++)
317 buffer.Append(terms[j].Text());
318 if (j < terms.Length - 1)
319 buffer.Append(" ");
321 buffer.Append(")");
323 else
325 buffer.Append(terms[0].Text());
328 buffer.Append("\"");
330 if (slop != 0)
332 buffer.Append("~");
333 buffer.Append(slop);
336 buffer.Append(ToStringUtils.Boost(GetBoost()));
338 return buffer.ToString();