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> 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.
35 /// <author> Anders Nielsen
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));
48 /// <summary>Sets the phrase slop for this query.</summary>
49 /// <seealso cref="PhraseQuery.SetSlop(int)">
51 public virtual void SetSlop(int s
)
56 /// <summary>Sets the phrase slop for this query.</summary>
57 /// <seealso cref="PhraseQuery.GetSlop()">
59 public virtual int GetSlop()
64 /// <summary>Add a single term at the next position in the phrase.</summary>
65 /// <seealso cref="PhraseQuery.Add(Term)">
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
76 /// <seealso cref="PhraseQuery.Add(Term)">
78 public virtual void Add(Term
[] terms
)
81 if (positions
.Count
> 0)
82 position
= ((System
.Int32
) positions
[positions
.Count
- 1]) + 1;
87 /// <summary> Allows to specify the relative position of terms within the phrase.
90 /// <seealso cref="PhraseQuery.Add(Term, int)">
92 /// <param name="terms">
94 /// <param name="position">
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
]);
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
;
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
);
150 System
.Collections
.IEnumerator i
= Enclosing_Instance
.termArrays
.GetEnumerator();
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
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
];
195 if (terms
.Length
> 1)
196 p
= new MultipleTermPositions(reader
, terms
);
198 p
= reader
.TermPositions(terms
[0]);
206 if (Enclosing_Instance
.slop
== 0)
207 return new ExactPhraseScorer(this, tps
, Enclosing_Instance
.GetPositions(), similarity
, reader
.Norms(Enclosing_Instance
.field
));
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
);
256 result
.SetValue(queryExpl
.GetValue() * fieldExpl
.GetValue());
258 if (queryExpl
.GetValue() == 1.0f
)
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());
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
);
300 bool appendSpace
= false;
303 System
.Collections
.IEnumerator i
= termArrays
.GetEnumerator();
306 if (appendSpace
== true)
311 Term
[] terms
= (Term
[]) i
.Current
;
312 if (terms
.Length
> 1)
315 for (int j
= 0; j
< terms
.Length
; j
++)
317 buffer
.Append(terms
[j
].Text());
318 if (j
< terms
.Length
- 1)
325 buffer
.Append(terms
[0].Text());
336 buffer
.Append(ToStringUtils
.Boost(GetBoost()));
338 return buffer
.ToString();