写一篇最好懂的lucene讲解

阳光穿透心脏的1/2处 2023-07-23 15:58 33阅读 0赞

Directory directory = FSDirectory.open(new File(“d:\\indexDir”));这行代码报错?

解决方案:

问题的缘由就是Lucene版本不兼容,下面的FSDirectory.open()在Lucene5.0.0版本下,open的参数是Path而不是File。

  1. String path = " ... ";
  2. directory = FSDirectory.open(new File(path));

所以在Lucene5.0.0版本下,正确的打开方式如下,这样得到的就是File,然后能正常赋给directory了。

  1. String path = " ... ";
  2. directory = FSDirectory.open(Paths.get(path));

maven依赖:

  1. <apache.lucene>5.5.5</apache.lucene>
  2. <dependency>
  3. <groupId>org.apache.lucene</groupId>
  4. <artifactId>lucene-analyzers-smartcn</artifactId>
  5. <version>${apache.lucene}</version>
  6. </dependency>
  7. <dependency>
  8. <groupId>org.apache.lucene</groupId>
  9. <artifactId>lucene-highlighter</artifactId>
  10. <version>${apache.lucene}</version>
  11. </dependency>

Lucene之索引查看工具Luke-yellowcong

http://www.getopt.org/luke/

DmitryKey/luke

v2-3fabb4ab6ba2b0b2d82f404f05143fc2\_b.jpg

开启:

java -jar lukeall-0.9.9.jar / 双击

代码实现:

  1. package com.mtons.mblog.modules.service.impl;
  2. import com.mtons.mblog.BootApplication;
  3. import org.apache.lucene.analysis.Analyzer;
  4. import org.apache.lucene.analysis.standard.StandardAnalyzer;
  5. import org.apache.lucene.document.Document;
  6. import org.apache.lucene.document.Field;
  7. import org.apache.lucene.document.StringField;
  8. import org.apache.lucene.document.TextField;
  9. import org.apache.lucene.index.*;
  10. import org.apache.lucene.search.*;
  11. import org.apache.lucene.store.Directory;
  12. import org.apache.lucene.store.FSDirectory;
  13. import org.junit.Test;
  14. import org.junit.runner.RunWith;
  15. import org.springframework.beans.factory.annotation.Autowired;
  16. import org.springframework.boot.test.context.SpringBootTest;
  17. import org.springframework.test.context.junit4.SpringRunner;
  18. import java.nio.file.Paths;
  19. import java.util.ArrayList;
  20. import java.util.Collection;
  21. @RunWith(SpringRunner.class)
  22. @SpringBootTest(classes = BootApplication.class)
  23. public class PostSearchInfoTest {
  24. @Autowired
  25. PostServiceImpl postService;
  26. @Test
  27. public void cleanPostPic() {
  28. }
  29. // 创建索引
  30. @Test
  31. public void testCreate() throws Exception{
  32. //1 创建文档对象
  33. Document document = new Document();
  34. // 创建并添加字段信息。参数:字段的名称、字段的值、是否存储,这里选Store.YES代表存储到文档列表。Store.NO代表不存储
  35. document.add(new StringField("id", "1", Field.Store.YES));
  36. // 这里我们title字段需要用TextField,即创建索引又会被分词。StringField会创建索引,但是不会被分词
  37. document.add(new TextField("title", "谷歌地图之父跳槽facebook", Field.Store.YES));
  38. //2 索引目录类,指定索引在硬盘中的位置
  39. String path = "d:\\indexDir";
  40. //Directory directory = FSDirectory.open(new File("d:\\indexDir"));
  41. Directory directory = FSDirectory.open(Paths.get(path));
  42. //3 创建分词器对象
  43. Analyzer analyzer = new StandardAnalyzer();
  44. //4 索引写出工具的配置对象
  45. IndexWriterConfig conf = new IndexWriterConfig(analyzer);
  46. //5 创建索引的写出工具类。参数:索引的目录和配置信息
  47. IndexWriter indexWriter = new IndexWriter(directory, conf);
  48. //6 把文档交给IndexWriter
  49. indexWriter.addDocument(document);
  50. //7 提交
  51. indexWriter.commit();
  52. //8 关闭
  53. indexWriter.close();
  54. }
  55. // 批量创建索引
  56. @Test
  57. public void testCreate2() throws Exception{
  58. // 创建文档的集合
  59. Collection<Document> docs = new ArrayList<>();
  60. // 创建文档对象
  61. Document document1 = new Document();
  62. document1.add(new StringField("id", "1", Field.Store.YES));
  63. document1.add(new TextField("title", "liyunfeng", Field.Store.YES));
  64. docs.add(document1);
  65. // 创建文档对象
  66. Document document2 = new Document();
  67. document2.add(new StringField("id", "2", Field.Store.YES));
  68. document2.add(new TextField("title", "谷歌地图之父加盟FaceBook", Field.Store.YES));
  69. docs.add(document2);
  70. // 创建文档对象
  71. Document document3 = new Document();
  72. document3.add(new StringField("id", "3", Field.Store.YES));
  73. document3.add(new TextField("title", "谷歌地图创始人拉斯离开谷歌加盟Facebook", Field.Store.YES));
  74. docs.add(document3);
  75. // 创建文档对象
  76. Document document4 = new Document();
  77. document4.add(new StringField("id", "4", Field.Store.YES));
  78. document4.add(new TextField("title", "谷歌地图之父跳槽Facebook与Wave项目取消有关", Field.Store.YES));
  79. docs.add(document4);
  80. // 创建文档对象
  81. Document document5 = new Document();
  82. document5.add(new StringField("id", "5", Field.Store.YES));
  83. document5.add(new TextField("title", "谷歌地图之父拉斯加盟社交网站Facebook", Field.Store.YES));
  84. docs.add(document5);
  85. // 索引目录类,指定索引在硬盘中的位置
  86. String path = "d:\\indexDir";
  87. //Directory directory = FSDirectory.open(new File("d:\\indexDir"));
  88. Directory directory = FSDirectory.open(Paths.get(path));
  89. // 引入IK分词器
  90. Analyzer analyzer = new StandardAnalyzer();
  91. // 索引写出工具的配置对象
  92. IndexWriterConfig conf = new IndexWriterConfig(analyzer);
  93. // 设置打开方式:OpenMode.APPEND 会在索引库的基础上追加新索引。OpenMode.CREATE会先清空原来数据,再提交新的索引
  94. conf.setOpenMode(IndexWriterConfig.OpenMode.CREATE);
  95. // 创建索引的写出工具类。参数:索引的目录和配置信息
  96. IndexWriter indexWriter = new IndexWriter(directory, conf);
  97. // 把文档集合交给IndexWriter
  98. indexWriter.addDocuments(docs);
  99. // 提交
  100. indexWriter.commit();
  101. // 关闭
  102. indexWriter.close();
  103. }
  104. public void search(Query query) throws Exception {
  105. // 索引目录对象
  106. String path = "D:\\indexDir";
  107. //Directory directory = FSDirectory.open(new File("d:\\indexDir"));
  108. Directory directory = FSDirectory.open(Paths.get(path));
  109. // 索引读取工具
  110. IndexReader reader = DirectoryReader.open(directory);
  111. // 索引搜索工具
  112. IndexSearcher searcher = new IndexSearcher(reader);
  113. // 搜索数据,两个参数:查询条件对象要查询的最大结果条数
  114. // 返回的结果是 按照匹配度排名得分前N名的文档信息(包含查询到的总条数信息、所有符合条件的文档的编号信息)。
  115. TopDocs topDocs = searcher.search(query, 10);
  116. // 获取总条数
  117. System.out.println("本次搜索共找到" + topDocs.totalHits + "条数据");
  118. // 获取得分文档对象(ScoreDoc)数组.SocreDoc中包含:文档的编号、文档的得分
  119. ScoreDoc[] scoreDocs = topDocs.scoreDocs;
  120. for (ScoreDoc scoreDoc : scoreDocs) {
  121. // 取出文档编号
  122. int docID = scoreDoc.doc;
  123. // 根据编号去找文档
  124. Document doc = reader.document(docID);
  125. System.out.println("id: " + doc.get("id"));
  126. System.out.println("title: " + doc.get("title"));
  127. // 取出文档得分
  128. System.out.println("得分: " + scoreDoc.score);
  129. }
  130. }
  131. /*
  132. * 测试普通词条查询
  133. * 注意:Term(词条)是搜索的最小单位,不可再分词。值必须是字符串!
  134. */
  135. @Test
  136. public void testTermQuery() throws Exception {
  137. // 创建词条查询对象
  138. Query query = new TermQuery(new Term("title", "谷歌地图"));
  139. search(query);
  140. }
  141. /*
  142. * 测试通配符查询
  143. * ? 可以代表任意一个字符
  144. * * 可以任意多个任意字符
  145. */
  146. @Test
  147. public void testWildCardQuery() throws Exception {
  148. // 创建查询对象
  149. Query query = new WildcardQuery(new Term("title", "*liyunfeng*"));
  150. search(query);
  151. }
  152. /*
  153. * 测试:数值范围查询
  154. * 注意:数值范围查询,可以用来对非String类型的ID进行精确的查找
  155. */
  156. @Test
  157. public void testNumericRangeQuery() throws Exception{
  158. // 数值范围查询对象,参数:字段名称,最小值、最大值、是否包含最小值、是否包含最大值
  159. Query query = NumericRangeQuery.newLongRange("id", 2L, 2L, true, true);
  160. search(query);
  161. }
  162. /*
  163. * 布尔查询:
  164. * 布尔查询本身没有查询条件,可以把其它查询通过逻辑运算进行组合!
  165. * 交集:Occur.MUST + Occur.MUST
  166. * 并集:Occur.SHOULD + Occur.SHOULD
  167. * 非:Occur.MUST_NOT
  168. */
  169. @Test
  170. public void testBooleanQuery() throws Exception{
  171. Query query1 = NumericRangeQuery.newLongRange("id", 1L, 3L, true, true);
  172. Query query2 = NumericRangeQuery.newLongRange("id", 2L, 4L, true, true);
  173. // 创建布尔查询的对象
  174. BooleanQuery query = new BooleanQuery();
  175. // 组合其它查询
  176. query.add(query1, BooleanClause.Occur.MUST_NOT);
  177. query.add(query2, BooleanClause.Occur.SHOULD);
  178. search(query);
  179. }
  180. /*
  181. * 测试模糊查询
  182. */
  183. @Test
  184. public void testFuzzyQuery() throws Exception {
  185. // 创建模糊查询对象:允许用户输错。但是要求错误的最大编辑距离不能超过2
  186. // 编辑距离:一个单词到另一个单词最少要修改的次数 facebool --> facebook 需要编辑1次,编辑距离就是1
  187. // Query query = new FuzzyQuery(new Term("title","fscevool"));
  188. // 可以手动指定编辑距离,但是参数必须在0~2之间
  189. Query query = new FuzzyQuery(new Term("title","谷歌地图之父跳槽faceboog"),1);
  190. search(query);
  191. }
  192. @Test
  193. public void testUpdate() throws Exception{
  194. // 创建目录对象
  195. String path = "D:\\indexDir";
  196. //Directory directory = FSDirectory.open(new File("d:\\indexDir"));
  197. Directory directory = FSDirectory.open(Paths.get(path));
  198. // 创建配置对象
  199. Analyzer analyzer = new StandardAnalyzer();
  200. IndexWriterConfig conf = new IndexWriterConfig(analyzer);
  201. // 创建索引写出工具
  202. IndexWriter writer = new IndexWriter(directory, conf);
  203. // 创建新的文档数据
  204. Document doc = new Document();
  205. doc.add(new StringField("id","1", Field.Store.YES));
  206. doc.add(new TextField("title","谷歌地图之父跳槽facebook ", Field.Store.YES));
  207. /* 修改索引。参数:
  208. * 词条:根据这个词条匹配到的所有文档都会被修改
  209. * 文档信息:要修改的新的文档数据
  210. */
  211. writer.updateDocument(new Term("id","1"), doc);
  212. // 提交
  213. writer.commit();
  214. // 关闭
  215. writer.close();
  216. }
  217. /*
  218. * 演示:删除索引
  219. * 注意:
  220. * 一般,为了进行精确删除,我们会根据唯一字段来删除。比如ID
  221. * 如果是用Term删除,要求ID也必须是字符串类型!
  222. */
  223. @Test
  224. public void testDelete() throws Exception {
  225. // 创建目录对象
  226. String path = "D:\\indexDir";
  227. //Directory directory = FSDirectory.open(new File("d:\\indexDir"));
  228. Directory directory = FSDirectory.open(Paths.get(path));
  229. // 创建配置对象
  230. Analyzer analyzer = new StandardAnalyzer();
  231. // 索引写出工具的配置对象
  232. IndexWriterConfig conf = new IndexWriterConfig(analyzer);
  233. // 创建索引写出工具
  234. IndexWriter writer = new IndexWriter(directory, conf);
  235. // 根据词条进行删除
  236. // writer.deleteDocuments(new Term("id", "1"));
  237. // 根据query对象删除,如果ID是数值类型,那么我们可以用数值范围查询锁定一个具体的ID
  238. // Query query = NumericRangeQuery.newLongRange("id", 2L, 2L, true, true);
  239. // writer.deleteDocuments(query);
  240. // 删除所有
  241. writer.deleteAll();
  242. // 提交
  243. writer.commit();
  244. // 关闭
  245. writer.close();
  246. }
  247. }

输出:

v2-04850168178f17ffbd32aa2f39932781\_b.jpg

发表评论

表情:
评论列表 (有 0 条评论,33人围观)

还没有评论,来说两句吧...

相关阅读