lucene的多种搜索2-SpanQuery

时间:2022-01-23 15:30:03

SpanQuery按照词在文章中的距离或者查询几个相邻词的查询

SpanQuery包括以下几种:

SpanTermQuery:词距查询的基础,结果和TermQuery相似,只不过是增加了查询结果中单词的距离信息。

SpanFirstQuery:在指定距离可以找到第一个单词的查询。

SpanNearQuery:查询的几个语句之间保持者一定的距离。

SpanOrQuery:同时查询几个词句查询。

SpanNotQuery:从一个词距查询结果中,去除一个词距查询。

下面一个简单例子介绍

  1. package com;
  2. //SpanQuery:跨度查询。此类为抽象类。
  3. import java.io.IOException;
  4. import java.io.StringReader;
  5. import java.util.ArrayList;
  6. import java.util.List;
  7. import org.apache.lucene.analysis.Analyzer;
  8. import org.apache.lucene.analysis.Token;
  9. import org.apache.lucene.analysis.TokenStream;
  10. import org.apache.lucene.analysis.WhitespaceAnalyzer;
  11. import org.apache.lucene.document.Document;
  12. import org.apache.lucene.document.Field;
  13. import org.apache.lucene.document.Field.Index;
  14. import org.apache.lucene.document.Field.Store;
  15. import org.apache.lucene.index.IndexReader;
  16. import org.apache.lucene.index.IndexWriter;
  17. import org.apache.lucene.index.Term;
  18. import org.apache.lucene.search.Hits;
  19. import org.apache.lucene.search.IndexSearcher;
  20. import org.apache.lucene.search.spans.SpanFirstQuery;
  21. import org.apache.lucene.search.spans.SpanNearQuery;
  22. import org.apache.lucene.search.spans.SpanNotQuery;
  23. import org.apache.lucene.search.spans.SpanOrQuery;
  24. import org.apache.lucene.search.spans.SpanQuery;
  25. import org.apache.lucene.search.spans.SpanTermQuery;
  26. import org.apache.lucene.search.spans.Spans;
  27. import org.apache.lucene.store.RAMDirectory;
  28. public class SpanQueryTest {
  29. private RAMDirectory directory;
  30. private IndexSearcher indexSearcher;
  31. private IndexReader reader;
  32. private SpanTermQuery quick;
  33. private SpanTermQuery brown;
  34. private SpanTermQuery red;
  35. private SpanTermQuery fox;
  36. private SpanTermQuery lazy;
  37. private SpanTermQuery sleepy;
  38. private SpanTermQuery dog;
  39. private SpanTermQuery cat;
  40. private Analyzer analyzer;
  41. // 索引及初使化
  42. public void index() throws IOException {
  43. directory = new RAMDirectory();
  44. analyzer = new WhitespaceAnalyzer();
  45. IndexWriter writer = new IndexWriter(directory, analyzer, true);
  46. Document doc1 = new Document();
  47. doc1.add(new Field("field",
  48. "the quick brown fox jumps over the lazy dog", Store.YES,
  49. Index.TOKENIZED));
  50. Document doc2 = new Document();
  51. doc2.add(new Field("field",
  52. "the quick red fox jumps over the sleepy cat", Store.YES,
  53. Index.TOKENIZED));
  54. writer.addDocument(doc1);
  55. writer.addDocument(doc2);
  56. writer.optimize();
  57. writer.close();
  58. quick = new SpanTermQuery(new Term("field", "quick"));
  59. brown = new SpanTermQuery(new Term("field", "brown"));
  60. red = new SpanTermQuery(new Term("field", "red"));
  61. fox = new SpanTermQuery(new Term("field", "fox"));
  62. lazy = new SpanTermQuery(new Term("field", "lazy"));
  63. sleepy = new SpanTermQuery(new Term("field", "sleepy"));
  64. dog = new SpanTermQuery(new Term("field", "dog"));
  65. cat = new SpanTermQuery(new Term("field", "cat"));
  66. indexSearcher = new IndexSearcher(directory);
  67. reader = IndexReader.open(directory);
  68. }
  69. private void dumpSpans(SpanQuery query) throws IOException {
  70. // 检索效果和TermQuery一样,可以把他当成TermQuery
  71. Hits hits = indexSearcher.search(query);
  72. for (int i = ; i < hits.length(); i++) {
  73. // System.out.println(hits.doc(i).get("field"));
  74. }
  75. // 但内部会记录一些位置信息,供SpanQuery的其它API使用,是其它属于SpanQuery的Query的基础。
  76. Spans spans = query.getSpans(reader);
  77. int numSpans = ;
  78. float[] scores = new float[];
  79. for (int i = ; i < hits.length(); i++) {
  80. scores[hits.id(i)] = hits.score(i);
  81. }
  82. while (spans.next()) {
  83. numSpans++;
  84. int id = spans.doc();
  85. Document doc = reader.document(id);
  86. Token[] tokens = AnalyzerUtils.tokensFromAnalysis(analyzer, doc
  87. .get("field"));
  88. StringBuffer buffer = new StringBuffer();
  89. for (int i = ; i < tokens.length; i++) {
  90. // the quick brown fox jumps over the lazy dog
  91. // spans记录了位置信息,比如搜索brown,brown在这句话中位于第三个位置,所以spans.start()=2,spans.end()=3
  92. // 在第二项的位置后加<,第三项后加> 返回<brown>
  93. if (i == spans.start()) {
  94. buffer.append("<");
  95. }
  96. buffer.append(tokens[i].termText());
  97. if (i +  == spans.end()) {
  98. buffer.append(">");
  99. }
  100. buffer.append(" ");
  101. }
  102. buffer.append("(" + scores[id] + ") ");
  103. System.out.println(buffer);
  104. }
  105. // indexSearcher.close();
  106. }
  107. // SpanTermQuery:检索效果完全同TermQuery,但内部会记录一些位置信息,供SpanQuery的其它API使用,是其它属于SpanQuery的Query的基础。
  108. public void spanTermQueryTest() throws IOException {
  109. dumpSpans(brown);
  110. //// 搜索结果
  111. // the quick <brown> fox jumps over the lazy dog (0.22097087)
  112. }
  113. // SpanFirstQuery:查找方式为从Field的内容起始位置开始,在一个固定的宽度内查找所指定的词条。
  114. public void spanFirstQueryTest() throws IOException {
  115. // the quick brown fox jumps over the lazy dog
  116. // 在给定的范围搜索,前两个为the quick
  117. // brown 在doc1的第三个位置,用SpanFirstQuery从起点查找的话,他的跨度必须为>=3才能找到
  118. SpanFirstQuery firstQuery = new SpanFirstQuery(brown, );
  119. dumpSpans(firstQuery);
  120. ////搜索结果
  121. // the quick <brown> fox jumps over the lazy dog (0.22097087)
  122. }
  123. // SpanNearQuery:功能类似PharaseQuery。SpanNearQuery查找所匹配的不一定是短语,还有可能是另一个SpanQuery的查询结果作为整体考虑,进行嵌套查询。
  124. public void spanNearQueryTest() throws IOException {
  125. // the quick brown fox jumps over the lazy dog
  126. // 第二个参数为两个项的位置之间允许的最大间隔
  127. // 在这里两个较远的项为quick和fox,他们之是的最大间隔为5,所以slop必须>=5才能搜到结果
  128. SpanNearQuery nearQuery = new SpanNearQuery(new SpanQuery[] { quick,
  129. brown, fox }, , true);
  130. dumpSpans(nearQuery);
  131. // 与PhraseQuery短语搜索相似
  132. // 这里搜索quick,dog,brown,要想得到结果,就要将brown向后移动5个位置才能到dog的后面,所以slop要>=5才能找到结果
  133. // 第三个参数,如果为true表示保持各项位置不变,顺序搜索
  134. nearQuery = new SpanNearQuery(new SpanQuery[] { quick, dog, brown }, ,
  135. false);
  136. dumpSpans(nearQuery);
  137. //////搜索结果/////
  138. // 第一个dumpSpans的结果 the <quick brown fox> jumps over the lazy dog (0.34204215)
  139. // 第二个dumpSpans的结果 the <quick brown fox jumps over the lazy dog> (0.27026406)
  140. }
  141. // 从第一个SpanQuery查询结果中,去掉第二个SpanQuery查询结果,作为检索结果
  142. public void spanNotQueryTest() throws IOException {
  143. // the quick brown fox jumps over the lazy dog
  144. SpanNearQuery quick_fox = new SpanNearQuery(new SpanQuery[] { quick,
  145. fox }, , true);
  146. // 结果为quick brown fox 和 quick red fox
  147. dumpSpans(quick_fox);
  148. // SpanNotQuery quick_fox_dog = new SpanNotQuery(quick_fox, dog);
  149. //
  150. // dumpSpans(quick_fox_dog);
  151. // 在quick_fox结果中,去掉red,结果为quick brown fox
  152. SpanNotQuery no_quick_red_fox = new SpanNotQuery(quick_fox, red);
  153. dumpSpans(no_quick_red_fox);
  154. //////搜索结果///////第一个dumpSpans结果为前两条,第二个dumpSpans结果为第三条
  155. //the <quick brown fox> jumps over the lazy dog (0.18579213)
  156. //the <quick red fox> jumps over the sleepy cat (0.18579213)
  157. //the <quick brown fox> jumps over the lazy dog (0.18579213)
  158. }
  159. // SpanOrQuery:把所有SpanQuery查询结果综合起来,作为检索结果。
  160. public void spanOrQueryTest() throws IOException   {
  161. SpanNearQuery quick_fox = new SpanNearQuery(new SpanQuery[] { quick,
  162. fox }, , true);
  163. SpanNearQuery lazy_dog = new SpanNearQuery(
  164. new SpanQuery[] { lazy, dog }, , true);
  165. SpanNearQuery sleepy_cat = new SpanNearQuery(new SpanQuery[] { sleepy,
  166. cat }, , true);
  167. SpanNearQuery qf_near_ld = new SpanNearQuery(new SpanQuery[] {
  168. quick_fox, lazy_dog }, , true);
  169. dumpSpans(qf_near_ld);
  170. SpanNearQuery qf_near_sc = new SpanNearQuery(new SpanQuery[] {
  171. quick_fox, sleepy_cat }, , true);
  172. dumpSpans(qf_near_sc);
  173. SpanOrQuery or = new SpanOrQuery(new SpanQuery[] { qf_near_ld,
  174. qf_near_sc });
  175. dumpSpans(or);
  176. /////////搜索结果 第一个dumpSpans结果为第一条,第二个为第二条,第三个为第三,四条
  177. // the <quick brown fox jumps over the lazy dog> (0.3321948)
  178. // the <quick red fox jumps over the sleepy cat> (0.3321948)
  179. // the <quick brown fox jumps over the lazy dog> (0.5405281)
  180. // the <quick red fox jumps over the sleepy cat> (0.5405281)
  181. }
  182. public static void main(String[] args) throws IOException {
  183. SpanQueryTest test = new SpanQueryTest();
  184. test.index();
  185. test.spanOrQueryTest();
  186. }
  187. }
  188. class AnalyzerUtils {
  189. public static Token[] tokensFromAnalysis(Analyzer analyzer, String text)
  190. throws IOException {
  191. TokenStream stream = analyzer.tokenStream("contents", new StringReader(
  192. text));
  193. boolean b = true;
  194. List<Token> list = new ArrayList<Token>();
  195. while (b) {
  196. Token token = stream.next();
  197. if (token == null)
  198. b = false;
  199. else
  200. list.add(token);
  201. }
  202. return (Token[]) list.toArray(new Token[]);
  203. }
  204. }