2 * Copyright 2004 The Apache Software Foundation
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
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.
35 /// <deprecated> use {@link Lucene.Net.search.MultiPhraseQuery} instead
37 /// <author> Anders Nielsen
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));
50 /// <summary>Sets the phrase slop for this query.</summary>
51 /// <seealso cref="PhraseQuery.SetSlop(int)">
53 public virtual void SetSlop(int s
)
58 /// <summary>Sets the phrase slop for this query.</summary>
59 /// <seealso cref="PhraseQuery.GetSlop()">
61 public virtual int GetSlop()
66 /// <summary>Add a single term at the next position in the phrase.</summary>
67 /// <seealso cref="PhraseQuery.Add(Term)">
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
78 /// <seealso cref="PhraseQuery.Add(Term)">
80 public virtual void Add(Term
[] terms
)
83 if (positions
.Count
> 0)
84 position
= ((System
.Int32
) positions
[positions
.Count
- 1]) + 1;
89 /// <summary> Allows to specify the relative position of terms within the phrase.
92 /// <seealso cref="PhraseQuery.Add(Term, int)">
94 /// <param name="terms">
96 /// <param name="position">
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
]);
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
;
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
);
152 System
.Collections
.IEnumerator i
= Enclosing_Instance
.termArrays
.GetEnumerator();
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
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
];
197 if (terms
.Length
> 1)
198 p
= new MultipleTermPositions(reader
, terms
);
200 p
= reader
.TermPositions(terms
[0]);
208 if (Enclosing_Instance
.slop
== 0)
209 return new ExactPhraseScorer(this, tps
, Enclosing_Instance
.GetPositions(), similarity
, reader
.Norms(Enclosing_Instance
.field
));
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
);
258 result
.SetValue(queryExpl
.GetValue() * fieldExpl
.GetValue());
260 if (queryExpl
.GetValue() == 1.0f
)
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
);
295 System
.Collections
.IEnumerator i
= termArrays
.GetEnumerator();
298 Term
[] terms
= (Term
[]) i
.Current
;
299 buffer
.Append(terms
[0].Text() + (terms
.Length
> 1?"*":""));
311 buffer
.Append(ToStringUtils
.Boost(GetBoost()));
313 return buffer
.ToString();