MultiPhraseQuery.cs
上传用户:zhangkuixh
上传日期:2013-09-30
资源大小:5473k
文件大小:10k
源码类别:

搜索引擎

开发平台:

C#

  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.
  15.  */
  16. using System;
  17. using IndexReader = Lucene.Net.Index.IndexReader;
  18. using MultipleTermPositions = Lucene.Net.Index.MultipleTermPositions;
  19. using Term = Lucene.Net.Index.Term;
  20. using TermPositions = Lucene.Net.Index.TermPositions;
  21. using ToStringUtils = Lucene.Net.Util.ToStringUtils;
  22. namespace Lucene.Net.Search
  23. {
  24. /// <summary> MultiPhraseQuery is a generalized version of PhraseQuery, with an added
  25. /// method {@link #Add(Term[])}.
  26. /// To use this class, to search for the phrase "Microsoft app*" first use
  27. /// add(Term) on the term "Microsoft", then find all terms that have "app" as
  28. /// prefix using IndexReader.terms(Term), and use MultiPhraseQuery.add(Term[]
  29. /// terms) to add them to the query.
  30. /// 
  31. /// </summary>
  32. /// <author>  Anders Nielsen
  33. /// </author>
  34. /// <version>  1.0
  35. /// </version>
  36. [Serializable]
  37. public class MultiPhraseQuery : Query
  38. {
  39. private System.String field;
  40. private System.Collections.ArrayList termArrays = new System.Collections.ArrayList();
  41. private System.Collections.ArrayList positions = System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList(10));
  42. private int slop = 0;
  43. /// <summary>Sets the phrase slop for this query.</summary>
  44. /// <seealso cref="PhraseQuery.SetSlop(int)">
  45. /// </seealso>
  46. public virtual void  SetSlop(int s)
  47. {
  48. slop = s;
  49. }
  50. /// <summary>Sets the phrase slop for this query.</summary>
  51. /// <seealso cref="PhraseQuery.GetSlop()">
  52. /// </seealso>
  53. public virtual int GetSlop()
  54. {
  55. return slop;
  56. }
  57. /// <summary>Add a single term at the next position in the phrase.</summary>
  58. /// <seealso cref="PhraseQuery.Add(Term)">
  59. /// </seealso>
  60. public virtual void  Add(Term term)
  61. {
  62. Add(new Term[]{term});
  63. }
  64. /// <summary>Add multiple terms at the next position in the phrase.  Any of the terms
  65. /// may match.
  66. /// 
  67. /// </summary>
  68. /// <seealso cref="PhraseQuery.Add(Term)">
  69. /// </seealso>
  70. public virtual void  Add(Term[] terms)
  71. {
  72. int position = 0;
  73. if (positions.Count > 0)
  74. position = ((System.Int32) positions[positions.Count - 1]) + 1;
  75. Add(terms, position);
  76. }
  77. /// <summary> Allows to specify the relative position of terms within the phrase.
  78. /// 
  79. /// </summary>
  80. /// <seealso cref="PhraseQuery.Add(Term, int)">
  81. /// </seealso>
  82. /// <param name="terms">
  83. /// </param>
  84. /// <param name="position">
  85. /// </param>
  86. public virtual void  Add(Term[] terms, int position)
  87. {
  88. if (termArrays.Count == 0)
  89. field = terms[0].Field();
  90. for (int i = 0; i < terms.Length; i++)
  91. {
  92. if ((System.Object) terms[i].Field() != (System.Object) field)
  93. {
  94. throw new System.ArgumentException("All phrase terms must be in the same field (" + field + "): " + terms[i]);
  95. }
  96. }
  97. termArrays.Add(terms);
  98. positions.Add((System.Int32) position);
  99. }
  100. /// <summary> Returns the relative positions of terms in this phrase.</summary>
  101. public virtual int[] GetPositions()
  102. {
  103. int[] result = new int[positions.Count];
  104. for (int i = 0; i < positions.Count; i++)
  105. result[i] = ((System.Int32) positions[i]);
  106. return result;
  107. }
  108. [Serializable]
  109. private class MultiPhraseWeight : Weight
  110. {
  111. private void  InitBlock(MultiPhraseQuery enclosingInstance)
  112. {
  113. this.enclosingInstance = enclosingInstance;
  114. }
  115. private MultiPhraseQuery enclosingInstance;
  116. public MultiPhraseQuery Enclosing_Instance
  117. {
  118. get
  119. {
  120. return enclosingInstance;
  121. }
  122. }
  123. private Similarity similarity;
  124. private float value_Renamed;
  125. private float idf;
  126. private float queryNorm;
  127. private float queryWeight;
  128. public MultiPhraseWeight(MultiPhraseQuery enclosingInstance, Searcher searcher)
  129. {
  130. InitBlock(enclosingInstance);
  131. this.similarity = Enclosing_Instance.GetSimilarity(searcher);
  132. // compute idf
  133. System.Collections.IEnumerator i = Enclosing_Instance.termArrays.GetEnumerator();
  134. while (i.MoveNext())
  135. {
  136. Term[] terms = (Term[]) i.Current;
  137. for (int j = 0; j < terms.Length; j++)
  138. {
  139. idf += Enclosing_Instance.GetSimilarity(searcher).Idf(terms[j], searcher);
  140. }
  141. }
  142. }
  143. public virtual Query GetQuery()
  144. {
  145. return Enclosing_Instance;
  146. }
  147. public virtual float GetValue()
  148. {
  149. return value_Renamed;
  150. }
  151. public virtual float SumOfSquaredWeights()
  152. {
  153. queryWeight = idf * Enclosing_Instance.GetBoost(); // compute query weight
  154. return queryWeight * queryWeight; // square it
  155. }
  156. public virtual void  Normalize(float queryNorm)
  157. {
  158. this.queryNorm = queryNorm;
  159. queryWeight *= queryNorm; // normalize query weight
  160. value_Renamed = queryWeight * idf; // idf for document 
  161. }
  162. public virtual Scorer Scorer(IndexReader reader)
  163. {
  164. if (Enclosing_Instance.termArrays.Count == 0)
  165.      // optimize zero-term case
  166. return null;
  167. TermPositions[] tps = new TermPositions[Enclosing_Instance.termArrays.Count];
  168. for (int i = 0; i < tps.Length; i++)
  169. {
  170. Term[] terms = (Term[]) Enclosing_Instance.termArrays[i];
  171. TermPositions p;
  172. if (terms.Length > 1)
  173. p = new MultipleTermPositions(reader, terms);
  174. else
  175. p = reader.TermPositions(terms[0]);
  176. if (p == null)
  177. return null;
  178. tps[i] = p;
  179. }
  180. if (Enclosing_Instance.slop == 0)
  181. return new ExactPhraseScorer(this, tps, Enclosing_Instance.GetPositions(), similarity, reader.Norms(Enclosing_Instance.field));
  182. else
  183. return new SloppyPhraseScorer(this, tps, Enclosing_Instance.GetPositions(), similarity, Enclosing_Instance.slop, reader.Norms(Enclosing_Instance.field));
  184. }
  185. public virtual Explanation Explain(IndexReader reader, int doc)
  186. {
  187. Explanation result = new Explanation();
  188. result.SetDescription("weight(" + GetQuery() + " in " + doc + "), product of:");
  189. Explanation idfExpl = new Explanation(idf, "idf(" + GetQuery() + ")");
  190. // explain query weight
  191. Explanation queryExpl = new Explanation();
  192. queryExpl.SetDescription("queryWeight(" + GetQuery() + "), product of:");
  193. Explanation boostExpl = new Explanation(Enclosing_Instance.GetBoost(), "boost");
  194. if (Enclosing_Instance.GetBoost() != 1.0f)
  195. queryExpl.AddDetail(boostExpl);
  196. queryExpl.AddDetail(idfExpl);
  197. Explanation queryNormExpl = new Explanation(queryNorm, "queryNorm");
  198. queryExpl.AddDetail(queryNormExpl);
  199. queryExpl.SetValue(boostExpl.GetValue() * idfExpl.GetValue() * queryNormExpl.GetValue());
  200. result.AddDetail(queryExpl);
  201. // explain field weight
  202. Explanation fieldExpl = new Explanation();
  203. fieldExpl.SetDescription("fieldWeight(" + GetQuery() + " in " + doc + "), product of:");
  204. Explanation tfExpl = Scorer(reader).Explain(doc);
  205. fieldExpl.AddDetail(tfExpl);
  206. fieldExpl.AddDetail(idfExpl);
  207. Explanation fieldNormExpl = new Explanation();
  208. byte[] fieldNorms = reader.Norms(Enclosing_Instance.field);
  209. float fieldNorm = fieldNorms != null ? Similarity.DecodeNorm(fieldNorms[doc]) : 0.0f;
  210. fieldNormExpl.SetValue(fieldNorm);
  211. fieldNormExpl.SetDescription("fieldNorm(field=" + Enclosing_Instance.field + ", doc=" + doc + ")");
  212. fieldExpl.AddDetail(fieldNormExpl);
  213. fieldExpl.SetValue(tfExpl.GetValue() * idfExpl.GetValue() * fieldNormExpl.GetValue());
  214. result.AddDetail(fieldExpl);
  215. // combine them
  216. result.SetValue(queryExpl.GetValue() * fieldExpl.GetValue());
  217. if (queryExpl.GetValue() == 1.0f)
  218. return fieldExpl;
  219. return result;
  220. }
  221. }
  222. public override Query Rewrite(IndexReader reader)
  223. {
  224. if (termArrays.Count == 1)
  225. {
  226. // optimize one-term case
  227. Term[] terms = (Term[]) termArrays[0];
  228. BooleanQuery boq = new BooleanQuery(true);
  229. for (int i = 0; i < terms.Length; i++)
  230. {
  231. boq.Add(new TermQuery(terms[i]), BooleanClause.Occur.SHOULD);
  232. }
  233. boq.SetBoost(GetBoost());
  234. return boq;
  235. }
  236. else
  237. {
  238. return this;
  239. }
  240. }
  241. protected internal override Weight CreateWeight(Searcher searcher)
  242. {
  243. return new MultiPhraseWeight(this, searcher);
  244. }
  245. /// <summary>Prints a user-readable version of this query. </summary>
  246. public override System.String ToString(System.String f)
  247. {
  248. System.Text.StringBuilder buffer = new System.Text.StringBuilder();
  249. if (!field.Equals(f))
  250. {
  251. buffer.Append(field);
  252. buffer.Append(":");
  253. }
  254. buffer.Append(""");
  255. System.Collections.IEnumerator i = termArrays.GetEnumerator();
  256. while (i.MoveNext())
  257. {
  258. Term[] terms = (Term[]) i.Current;
  259. if (terms.Length > 1)
  260. {
  261. buffer.Append("(");
  262. for (int j = 0; j < terms.Length; j++)
  263. {
  264. buffer.Append(terms[j].Text());
  265. if (j < terms.Length - 1)
  266. buffer.Append(" ");
  267. }
  268. buffer.Append(")");
  269. }
  270. else
  271. {
  272. buffer.Append(terms[0].Text());
  273. }
  274. if (i.MoveNext())
  275. buffer.Append(" ");
  276. }
  277. buffer.Append(""");
  278. if (slop != 0)
  279. {
  280. buffer.Append("~");
  281. buffer.Append(slop);
  282. }
  283. buffer.Append(ToStringUtils.Boost(GetBoost()));
  284. return buffer.ToString();
  285. }
  286.         // {{Aroush-1.9}} Do we need this?!
  287.         override public System.Object Clone()
  288. {
  289. return null;
  290. }
  291. }
  292. }