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

搜索引擎

开发平台:

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 Analyzer = Lucene.Net.Analysis.Analyzer;
  18. using BooleanClause = Lucene.Net.Search.BooleanClause;
  19. using BooleanQuery = Lucene.Net.Search.BooleanQuery;
  20. using MultiPhraseQuery = Lucene.Net.Search.MultiPhraseQuery;
  21. using PhraseQuery = Lucene.Net.Search.PhraseQuery;
  22. using Query = Lucene.Net.Search.Query;
  23. namespace Lucene.Net.QueryParsers
  24. {
  25. /// <summary> A QueryParser which constructs queries to search multiple fields.
  26. /// 
  27. /// </summary>
  28. /// <author>  <a href="mailto:kelvin@relevanz.com">Kelvin Tan</a>, Daniel Naber
  29. /// </author>
  30. /// <version>  $Revision: 295117 $
  31. /// </version>
  32. public class MultiFieldQueryParser : QueryParser
  33. {
  34. private System.String[] fields;
  35. /// <summary> Creates a MultiFieldQueryParser.
  36. /// 
  37. /// <p>It will, when parse(String query)
  38. /// is called, construct a query like this (assuming the query consists of
  39. /// two terms and you specify the two fields <code>title</code> and <code>body</code>):</p>
  40. /// 
  41. /// <code>
  42. /// (title:term1 body:term1) (title:term2 body:term2)
  43. /// </code>
  44. /// 
  45. /// <p>When setDefaultOperator(AND_OPERATOR) is set, the result will be:</p>
  46. /// 
  47. /// <code>
  48. /// +(title:term1 body:term1) +(title:term2 body:term2)
  49. /// </code>
  50. /// 
  51. /// <p>In other words, all the query's terms must appear, but it doesn't matter in
  52. /// what fields they appear.</p>
  53. /// </summary>
  54. public MultiFieldQueryParser(System.String[] fields, Analyzer analyzer) : base(null, analyzer)
  55. {
  56. this.fields = fields;
  57. }
  58. protected internal override Query GetFieldQuery(System.String field, System.String queryText, int slop)
  59. {
  60. if (field == null)
  61. {
  62. System.Collections.ArrayList clauses = System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList(10));
  63. for (int i = 0; i < fields.Length; i++)
  64. {
  65. Query q = base.GetFieldQuery(fields[i], queryText);
  66. if (q != null)
  67. {
  68. if (q is PhraseQuery)
  69. {
  70. ((PhraseQuery) q).SetSlop(slop);
  71. }
  72. if (q is MultiPhraseQuery)
  73. {
  74. ((MultiPhraseQuery) q).SetSlop(slop);
  75. }
  76. clauses.Add(new BooleanClause(q, BooleanClause.Occur.SHOULD));
  77. }
  78. }
  79. if (clauses.Count == 0)
  80. // happens for stopwords
  81. return null;
  82. return GetBooleanQuery(clauses, true);
  83. }
  84. return base.GetFieldQuery(field, queryText);
  85. }
  86. protected internal override Query GetFieldQuery(System.String field, System.String queryText)
  87. {
  88. return GetFieldQuery(field, queryText, 0);
  89. }
  90. /// <deprecated> use {@link #GetFieldQuery(String, String)}
  91. /// </deprecated>
  92. protected internal override Query GetFieldQuery(System.String field, Analyzer analyzer, System.String queryText)
  93. {
  94. return GetFieldQuery(field, queryText);
  95. }
  96. /// <deprecated> use {@link #GetFuzzyQuery(String, String, float)}
  97. /// </deprecated>
  98. protected internal override Query GetFuzzyQuery(System.String field, System.String termStr)
  99. {
  100. return GetFuzzyQuery(field, termStr, fuzzyMinSim);
  101. }
  102. protected internal override Query GetFuzzyQuery(System.String field, System.String termStr, float minSimilarity)
  103. {
  104. if (field == null)
  105. {
  106. System.Collections.ArrayList clauses = System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList(10));
  107. for (int i = 0; i < fields.Length; i++)
  108. {
  109. clauses.Add(new BooleanClause(base.GetFuzzyQuery(fields[i], termStr, minSimilarity), BooleanClause.Occur.SHOULD));
  110. }
  111. return GetBooleanQuery(clauses, true);
  112. }
  113. return base.GetFuzzyQuery(field, termStr, minSimilarity);
  114. }
  115. protected internal override Query GetPrefixQuery(System.String field, System.String termStr)
  116. {
  117. if (field == null)
  118. {
  119. System.Collections.ArrayList clauses = System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList(10));
  120. for (int i = 0; i < fields.Length; i++)
  121. {
  122. clauses.Add(new BooleanClause(base.GetPrefixQuery(fields[i], termStr), BooleanClause.Occur.SHOULD));
  123. }
  124. return GetBooleanQuery(clauses, true);
  125. }
  126. return base.GetPrefixQuery(field, termStr);
  127. }
  128. protected internal override Query GetWildcardQuery(System.String field, System.String termStr)
  129. {
  130. if (field == null)
  131. {
  132. System.Collections.ArrayList clauses = System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList(10));
  133. for (int i = 0; i < fields.Length; i++)
  134. {
  135. clauses.Add(new BooleanClause(base.GetWildcardQuery(fields[i], termStr), BooleanClause.Occur.SHOULD));
  136. }
  137. return GetBooleanQuery(clauses, true);
  138. }
  139. return base.GetWildcardQuery(field, termStr);
  140. }
  141. /// <throws>  ParseException </throws>
  142. /// <deprecated> use {@link #GetRangeQuery(String, String, String, boolean)}
  143. /// </deprecated>
  144. protected internal override Query GetRangeQuery(System.String field, Analyzer analyzer, System.String part1, System.String part2, bool inclusive)
  145. {
  146. return GetRangeQuery(field, part1, part2, inclusive);
  147. }
  148. protected internal override Query GetRangeQuery(System.String field, System.String part1, System.String part2, bool inclusive)
  149. {
  150. if (field == null)
  151. {
  152. System.Collections.ArrayList clauses = System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList(10));
  153. for (int i = 0; i < fields.Length; i++)
  154. {
  155. clauses.Add(new BooleanClause(base.GetRangeQuery(fields[i], part1, part2, inclusive), BooleanClause.Occur.SHOULD));
  156. }
  157. return GetBooleanQuery(clauses, true);
  158. }
  159. return base.GetRangeQuery(field, part1, part2, inclusive);
  160. }
  161. /// <deprecated> 
  162. /// </deprecated>
  163. public const int NORMAL_FIELD = 0;
  164. /// <deprecated> 
  165. /// </deprecated>
  166. public const int REQUIRED_FIELD = 1;
  167. /// <deprecated> 
  168. /// </deprecated>
  169. public const int PROHIBITED_FIELD = 2;
  170. /// <deprecated> use {@link #MultiFieldQueryParser(String[], Analyzer)} instead
  171. /// </deprecated>
  172. public MultiFieldQueryParser(QueryParserTokenManager tm):base(tm)
  173. {
  174. }
  175. /// <deprecated> use {@link #MultiFieldQueryParser(String[], Analyzer)} instead
  176. /// </deprecated>
  177. public MultiFieldQueryParser(CharStream stream):base(stream)
  178. {
  179. }
  180. /// <deprecated> use {@link #MultiFieldQueryParser(String[], Analyzer)} instead
  181. /// </deprecated>
  182. public MultiFieldQueryParser(System.String f, Analyzer a):base(f, a)
  183. {
  184. }
  185. /// <summary> Parses a query which searches on the fields specified.
  186. /// If x fields are specified, this effectively constructs:
  187. /// 
  188. /// <code>
  189. /// (field1:query) (field2:query) (field3:query)...(fieldx:query)
  190. /// </code>
  191. /// 
  192. /// </summary>
  193. /// <param name="query">Query string to parse
  194. /// </param>
  195. /// <param name="fields">Fields to search on
  196. /// </param>
  197. /// <param name="analyzer">Analyzer to use
  198. /// </param>
  199. /// <throws>  ParseException if query parsing fails </throws>
  200. /// <throws>  TokenMgrError if query parsing fails </throws>
  201. /// <deprecated> use {@link #Parse(String)} instead but note that it
  202. /// returns a different query for queries where all terms are required:
  203. /// its query excepts all terms, no matter in what field they occur whereas
  204. /// the query built by this (deprecated) method expected all terms in all fields 
  205. /// at the same time.
  206. /// </deprecated>
  207. public static Query Parse(System.String query, System.String[] fields, Analyzer analyzer)
  208. {
  209. BooleanQuery bQuery = new BooleanQuery();
  210. for (int i = 0; i < fields.Length; i++)
  211. {
  212. Query q = Parse(query, fields[i], analyzer);
  213. bQuery.Add(q, BooleanClause.Occur.SHOULD);
  214. }
  215. return bQuery;
  216. }
  217. /// <summary> Parses a query which searches on the fields specified.
  218. /// <p>
  219. /// If x fields are specified, this effectively constructs:
  220. /// <pre>
  221. /// <code>
  222. /// (field1:query1) (field2:query2) (field3:query3)...(fieldx:queryx)
  223. /// </code>
  224. /// </pre>
  225. /// </summary>
  226. /// <param name="queries">Queries strings to parse
  227. /// </param>
  228. /// <param name="fields">Fields to search on
  229. /// </param>
  230. /// <param name="analyzer">Analyzer to use
  231. /// </param>
  232. /// <throws>  ParseException if query parsing fails </throws>
  233. /// <throws>  TokenMgrError if query parsing fails </throws>
  234. /// <throws>  IllegalArgumentException if the length of the queries array differs </throws>
  235. /// <summary>  from the length of the fields array
  236. /// </summary>
  237. public static Query Parse(System.String[] queries, System.String[] fields, Analyzer analyzer)
  238. {
  239. if (queries.Length != fields.Length)
  240. throw new System.ArgumentException("queries.length != fields.length");
  241. BooleanQuery bQuery = new BooleanQuery();
  242. for (int i = 0; i < fields.Length; i++)
  243. {
  244. QueryParser qp = new QueryParser(fields[i], analyzer);
  245. Query q = qp.Parse(queries[i]);
  246. bQuery.Add(q, BooleanClause.Occur.SHOULD);
  247. }
  248. return bQuery;
  249. }
  250. /// <summary> Parses a query, searching on the fields specified.
  251. /// Use this if you need to specify certain fields as required,
  252. /// and others as prohibited.
  253. /// <p><pre>
  254. /// Usage:
  255. /// <code>
  256. /// String[] fields = {"filename", "contents", "description"};
  257. /// int[] flags = {MultiFieldQueryParser.NORMAL_FIELD,
  258. /// MultiFieldQueryParser.REQUIRED_FIELD,
  259. /// MultiFieldQueryParser.PROHIBITED_FIELD,};
  260. /// parse(query, fields, flags, analyzer);
  261. /// </code>
  262. /// </pre>
  263. /// <p>
  264. /// The code above would construct a query:
  265. /// <pre>
  266. /// <code>
  267. /// (filename:query) +(contents:query) -(description:query)
  268. /// </code>
  269. /// </pre>
  270. /// 
  271. /// </summary>
  272. /// <param name="query">Query string to parse
  273. /// </param>
  274. /// <param name="fields">Fields to search on
  275. /// </param>
  276. /// <param name="flags">Flags describing the fields
  277. /// </param>
  278. /// <param name="analyzer">Analyzer to use
  279. /// </param>
  280. /// <throws>  ParseException if query parsing fails </throws>
  281. /// <throws>  TokenMgrError if query parsing fails </throws>
  282. /// <throws>  IllegalArgumentException if the length of the fields array differs </throws>
  283. /// <summary>  from the length of the flags array
  284. /// </summary>
  285. /// <deprecated> use {@link #Parse(String, String[], BooleanClause.Occur[], Analyzer)} instead
  286. /// </deprecated>
  287. public static Query Parse(System.String query, System.String[] fields, int[] flags, Analyzer analyzer)
  288. {
  289. if (fields.Length != flags.Length)
  290. throw new System.ArgumentException("fields.length != flags.length");
  291. BooleanQuery bQuery = new BooleanQuery();
  292. for (int i = 0; i < fields.Length; i++)
  293. {
  294. QueryParser qp = new QueryParser(fields[i], analyzer);
  295. Query q = qp.Parse(query);
  296. int flag = flags[i];
  297. switch (flag)
  298. {
  299. case REQUIRED_FIELD: 
  300. bQuery.Add(q, BooleanClause.Occur.MUST);
  301. break;
  302. case PROHIBITED_FIELD: 
  303. bQuery.Add(q, BooleanClause.Occur.MUST_NOT);
  304. break;
  305. default: 
  306. bQuery.Add(q, BooleanClause.Occur.SHOULD);
  307. break;
  308. }
  309. }
  310. return bQuery;
  311. }
  312. /// <summary> Parses a query, searching on the fields specified.
  313. /// Use this if you need to specify certain fields as required,
  314. /// and others as prohibited.
  315. /// <p><pre>
  316. /// Usage:
  317. /// <code>
  318. /// String[] fields = {"filename", "contents", "description"};
  319. /// BooleanClause.Occur[] flags = {BooleanClause.Occur.SHOULD,
  320. /// BooleanClause.Occur.MUST,
  321. /// BooleanClause.Occur.MUST_NOT};
  322. /// MultiFieldQueryParser.parse("query", fields, flags, analyzer);
  323. /// </code>
  324. /// </pre>
  325. /// <p>
  326. /// The code above would construct a query:
  327. /// <pre>
  328. /// <code>
  329. /// (filename:query) +(contents:query) -(description:query)
  330. /// </code>
  331. /// </pre>
  332. /// 
  333. /// </summary>
  334. /// <param name="query">Query string to parse
  335. /// </param>
  336. /// <param name="fields">Fields to search on
  337. /// </param>
  338. /// <param name="flags">Flags describing the fields
  339. /// </param>
  340. /// <param name="analyzer">Analyzer to use
  341. /// </param>
  342. /// <throws>  ParseException if query parsing fails </throws>
  343. /// <throws>  TokenMgrError if query parsing fails </throws>
  344. /// <throws>  IllegalArgumentException if the length of the fields array differs </throws>
  345. /// <summary>  from the length of the flags array
  346. /// </summary>
  347. public static Query Parse(System.String query, System.String[] fields, BooleanClause.Occur[] flags, Analyzer analyzer)
  348. {
  349. if (fields.Length != flags.Length)
  350. throw new System.ArgumentException("fields.length != flags.length");
  351. BooleanQuery bQuery = new BooleanQuery();
  352. for (int i = 0; i < fields.Length; i++)
  353. {
  354. QueryParser qp = new QueryParser(fields[i], analyzer);
  355. Query q = qp.Parse(query);
  356. bQuery.Add(q, flags[i]);
  357. }
  358. return bQuery;
  359. }
  360. /// <summary> Parses a query, searching on the fields specified. Use this if you need to
  361. /// specify certain fields as required, and others as prohibited.
  362. /// <p>
  363. /// <pre>
  364. /// Usage:
  365. /// <code>
  366. /// String[] fields = { &quot;filename&quot;, &quot;contents&quot;, &quot;description&quot; };
  367. /// int[] flags = { MultiFieldQueryParser.NORMAL_FIELD,
  368. /// MultiFieldQueryParser.REQUIRED_FIELD,
  369. /// MultiFieldQueryParser.PROHIBITED_FIELD, };
  370. /// parse(query, fields, flags, analyzer);
  371. /// </code>
  372. /// </pre>
  373. /// 
  374. /// <p>
  375. /// The code above would construct a query:
  376. /// <pre>
  377. /// <code>
  378. /// (filename:query1) +(contents:query2) -(description:query3)
  379. /// </code>
  380. /// </pre>
  381. /// 
  382. /// </summary>
  383. /// <param name="queries">Queries string to parse
  384. /// </param>
  385. /// <param name="fields">Fields to search on
  386. /// </param>
  387. /// <param name="flags">Flags describing the fields
  388. /// </param>
  389. /// <param name="analyzer">Analyzer to use
  390. /// </param>
  391. /// <throws>  ParseException if query parsing fails </throws>
  392. /// <throws>  TokenMgrError if query parsing fails </throws>
  393. /// <throws>  IllegalArgumentException if the length of the queries, fields, and flags array differ </throws>
  394. /// <deprecated> use {@link #Parse(String[], String[], BooleanClause.Occur[], Analyzer)} instead
  395. /// </deprecated>
  396. public static Query Parse(System.String[] queries, System.String[] fields, int[] flags, Analyzer analyzer)
  397. {
  398. if (!(queries.Length == fields.Length && queries.Length == flags.Length))
  399. throw new System.ArgumentException("queries, fields, and flags array have have different length");
  400. BooleanQuery bQuery = new BooleanQuery();
  401. for (int i = 0; i < fields.Length; i++)
  402. {
  403. QueryParser qp = new QueryParser(fields[i], analyzer);
  404. Query q = qp.Parse(queries[i]);
  405. int flag = flags[i];
  406. switch (flag)
  407. {
  408. case REQUIRED_FIELD: 
  409. bQuery.Add(q, BooleanClause.Occur.MUST);
  410. break;
  411. case PROHIBITED_FIELD: 
  412. bQuery.Add(q, BooleanClause.Occur.MUST_NOT);
  413. break;
  414. default: 
  415. bQuery.Add(q, BooleanClause.Occur.SHOULD);
  416. break;
  417. }
  418. }
  419. return bQuery;
  420. }
  421. /// <summary> Parses a query, searching on the fields specified.
  422. /// Use this if you need to specify certain fields as required,
  423. /// and others as prohibited.
  424. /// <p><pre>
  425. /// Usage:
  426. /// <code>
  427. /// String[] query = {"query1", "query2", "query3"};
  428. /// String[] fields = {"filename", "contents", "description"};
  429. /// BooleanClause.Occur[] flags = {BooleanClause.Occur.SHOULD,
  430. /// BooleanClause.Occur.MUST,
  431. /// BooleanClause.Occur.MUST_NOT};
  432. /// MultiFieldQueryParser.parse(query, fields, flags, analyzer);
  433. /// </code>
  434. /// </pre>
  435. /// <p>
  436. /// The code above would construct a query:
  437. /// <pre>
  438. /// <code>
  439. /// (filename:query1) +(contents:query2) -(description:query3)
  440. /// </code>
  441. /// </pre>
  442. /// 
  443. /// </summary>
  444. /// <param name="queries">Queries string to parse
  445. /// </param>
  446. /// <param name="fields">Fields to search on
  447. /// </param>
  448. /// <param name="flags">Flags describing the fields
  449. /// </param>
  450. /// <param name="analyzer">Analyzer to use
  451. /// </param>
  452. /// <throws>  ParseException if query parsing fails </throws>
  453. /// <throws>  TokenMgrError if query parsing fails </throws>
  454. /// <throws>  IllegalArgumentException if the length of the queries, fields, </throws>
  455. /// <summary>  and flags array differ
  456. /// </summary>
  457. public static Query Parse(System.String[] queries, System.String[] fields, BooleanClause.Occur[] flags, Analyzer analyzer)
  458. {
  459. if (!(queries.Length == fields.Length && queries.Length == flags.Length))
  460. throw new System.ArgumentException("queries, fields, and flags array have have different length");
  461. BooleanQuery bQuery = new BooleanQuery();
  462. for (int i = 0; i < fields.Length; i++)
  463. {
  464. QueryParser qp = new QueryParser(fields[i], analyzer);
  465. Query q = qp.Parse(queries[i]);
  466. bQuery.Add(q, flags[i]);
  467. }
  468. return bQuery;
  469. }
  470. }
  471. }