lucene&solr 基础使用

傷城~ 2021-11-10 08:00 317阅读 0赞

lucene和solr:官网下载地址http://lucene.apache.org/

一般网站用solr比较多,但是想要了解solr的用法,我们需要首先了解一下lucene的使用方法。因为solr底层使用lucene开发的。

lucene

全文检索:
将非结构化数据中的一部分信息提取出来,重新组织,使其变得有一定结构,然后对此有一定结构的数据进行搜索,从而达到搜索相对快的目的。这部分从
非结构化数据中提取出的,然后重新组织的信息,我们称之为索引。
这种先建立索引,再对索引进行搜索的过程就叫做全文检索。

lucene实现全文检索的流程:
创建索引:
获取文档:通过io操作获取磁盘文档。
创建文档:
文档对象:每一个字段(属性)就是一个域
分析文档:
将一段原始内容分析后得到语汇单元。
每一个单词是一个Term,不同域中的相同单词,不是同一个Term。Term是一个map结构。
创建索引:
在索引库中保存了两个部分。1、索引 2、文档对象

  1. 查询索引:
  2. 用户查询入口
  3. 创建查询
  4. 执行查询
  5. 渲染结果

lucene全文检索流程

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L1ROVF9E_size_16_color_FFFFFF_t_70

要是用lucene,首先要在项目中导入常用的jar包。

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L1ROVF9E_size_16_color_FFFFFF_t_70 1

Lucene 入门 创建索引 查询索引

  1. /**
  2. * Lucene 入门 创建索引 查询索引
  3. *
  4. * @author lx
  5. *
  6. */
  7. public class FirstLucene {
  8. // 创建索引
  9. @Test
  10. public void testIndex() throws Exception {
  11. // 第一步:创建一个java工程,并导入jar包。
  12. // 第二步:创建一个indexwriter对象。
  13. Directory directory = FSDirectory.open(new File("D:\\temp\\index"));
  14. // Directory directory = new RAMDirectory();//保存索引到内存中 (内存索引库)
  15. // Analyzer analyzer = new StandardAnalyzer();// 官方推荐
  16. Analyzer analyzer = new IKAnalyzer();// 官方推荐
  17. IndexWriterConfig config = new IndexWriterConfig(Version.LATEST, analyzer);
  18. IndexWriter indexWriter = new IndexWriter(directory, config);
  19. // 1)指定索引库的存放位置Directory对象
  20. // 2)指定一个分析器,对文档内容进行分析。
  21. // 第三步:创建field对象,将field添加到document对象中。
  22. File f = new File("D:\\Lucene&solr\\searchsource");
  23. File[] listFiles = f.listFiles();
  24. for (File file : listFiles) {
  25. // 第三步:创建document对象。
  26. Document document = new Document();
  27. // 文件名称
  28. String file_name = file.getName();
  29. Field fileNameField = new TextField("fileName", file_name, Store.YES);
  30. // 文件大小
  31. long file_size = FileUtils.sizeOf(file);
  32. Field fileSizeField = new LongField("fileSize", file_size, Store.YES);
  33. // 文件路径
  34. String file_path = file.getPath();
  35. Field filePathField = new StoredField("filePath", file_path);
  36. // 文件内容
  37. String file_content = FileUtils.readFileToString(file);
  38. Field fileContentField = new TextField("fileContent", file_content, Store.NO);
  39. document.add(fileNameField);
  40. document.add(fileSizeField);
  41. document.add(filePathField);
  42. document.add(fileContentField);
  43. // 第四步:使用indexwriter对象将document对象写入索引库,此过程进行索引创建。并将索引和document对象写入索引库。
  44. indexWriter.addDocument(document);
  45. }
  46. // 第五步:关闭IndexWriter对象。
  47. indexWriter.close();
  48. }
  49. // 搜索索引
  50. @Test
  51. public void testSearch() throws Exception {
  52. // 第一步:创建一个Directory对象,也就是索引库存放的位置。
  53. Directory directory = FSDirectory.open(new File("D:\\temp\\index"));// 磁盘
  54. // 第二步:创建一个indexReader对象,需要指定Directory对象。
  55. IndexReader indexReader = DirectoryReader.open(directory);
  56. // 第三步:创建一个indexsearcher对象,需要指定IndexReader对象
  57. IndexSearcher indexSearcher = new IndexSearcher(indexReader);
  58. // 第四步:创建一个TermQuery对象,指定查询的域和查询的关键词。
  59. Query query = new TermQuery(new Term("fileName", "lucene"));
  60. // 第五步:执行查询。
  61. TopDocs topDocs = indexSearcher.search(query, 10);
  62. // 第六步:返回查询结果。遍历查询结果并输出。
  63. ScoreDoc[] scoreDocs = topDocs.scoreDocs;
  64. for (ScoreDoc scoreDoc : scoreDocs) {
  65. int doc = scoreDoc.doc;
  66. Document document = indexSearcher.doc(doc);
  67. // 文件名称
  68. String fileName = document.get("fileName");
  69. System.out.println(fileName);
  70. // 文件内容
  71. String fileContent = document.get("fileContent");
  72. System.out.println(fileContent);
  73. // 文件大小
  74. String fileSize = document.get("fileSize");
  75. System.out.println(fileSize);
  76. // 文件路径
  77. String filePath = document.get("filePath");
  78. System.out.println(filePath);
  79. System.out.println("------------");
  80. }
  81. // 第七步:关闭IndexReader对象
  82. indexReader.close();
  83. }
  84. // 查看标准分析器的分词效果
  85. @Test
  86. public void testTokenStream() throws Exception {
  87. // 创建一个标准分析器对象
  88. // Analyzer analyzer = new StandardAnalyzer();
  89. // Analyzer analyzer = new CJKAnalyzer();
  90. // Analyzer analyzer = new SmartChineseAnalyzer();
  91. Analyzer analyzer = new IKAnalyzer();
  92. // 获得tokenStream对象
  93. // 第一个参数:域名,可以随便给一个
  94. // 第二个参数:要分析的文本内容
  95. // TokenStream tokenStream = analyzer.tokenStream("test",
  96. // "The Spring Framework provides a comprehensive programming and configuration model.");
  97. TokenStream tokenStream = analyzer.tokenStream("test",
  98. "高富帅可以用二维表结构来逻辑表达实现的数据");
  99. // 添加一个引用,可以获得每个关键词
  100. CharTermAttribute charTermAttribute = tokenStream.addAttribute(CharTermAttribute.class);
  101. // 添加一个偏移量的引用,记录了关键词的开始位置以及结束位置
  102. OffsetAttribute offsetAttribute = tokenStream.addAttribute(OffsetAttribute.class);
  103. // 将指针调整到列表的头部
  104. tokenStream.reset();
  105. // 遍历关键词列表,通过incrementToken方法判断列表是否结束
  106. while (tokenStream.incrementToken()) {
  107. // 关键词的起始位置
  108. System.out.println("start->" + offsetAttribute.startOffset());
  109. // 取关键词
  110. System.out.println(charTermAttribute);
  111. // 结束位置
  112. System.out.println("end->" + offsetAttribute.endOffset());
  113. }
  114. tokenStream.close();
  115. }
  116. }

lucene索引维护,其实也就是索引的增、删、改、查。

  1. /**
  2. * 索引维护
  3. * 添加 入门程序
  4. * 删除
  5. * 修改
  6. * 查询 入门程序 精准查询
  7. * @author lx
  8. *
  9. */
  10. public class LuceneManager {
  11. //
  12. public IndexWriter getIndexWriter() throws Exception{
  13. // 第一步:创建一个java工程,并导入jar包。
  14. // 第二步:创建一个indexwriter对象。
  15. Directory directory = FSDirectory.open(new File("D:\\temp\\index"));
  16. // Directory directory = new RAMDirectory();//保存索引到内存中 (内存索引库)
  17. Analyzer analyzer = new StandardAnalyzer();// 官方推荐
  18. IndexWriterConfig config = new IndexWriterConfig(Version.LATEST, analyzer);
  19. return new IndexWriter(directory, config);
  20. }
  21. //全删除
  22. @Test
  23. public void testAllDelete() throws Exception {
  24. IndexWriter indexWriter = getIndexWriter();
  25. indexWriter.deleteAll();
  26. indexWriter.close();
  27. }
  28. //根据条件删除
  29. @Test
  30. public void testDelete() throws Exception {
  31. IndexWriter indexWriter = getIndexWriter();
  32. Query query = new TermQuery(new Term("fileName","apache"));
  33. indexWriter.deleteDocuments(query);
  34. indexWriter.close();
  35. }
  36. //修改
  37. @Test
  38. public void testUpdate() throws Exception {
  39. IndexWriter indexWriter = getIndexWriter();
  40. Document doc = new Document();
  41. doc.add(new TextField("fileN", "测试文件名",Store.YES));
  42. doc.add(new TextField("fileC", "测试文件内容",Store.YES));
  43. indexWriter.updateDocument(new Term("fileName","lucene"), doc, new IKAnalyzer());
  44. indexWriter.close();
  45. }
  46. //IndexReader IndexSearcher
  47. public IndexSearcher getIndexSearcher() throws Exception{
  48. // 第一步:创建一个Directory对象,也就是索引库存放的位置。
  49. Directory directory = FSDirectory.open(new File("D:\\temp\\index"));// 磁盘
  50. // 第二步:创建一个indexReader对象,需要指定Directory对象。
  51. IndexReader indexReader = DirectoryReader.open(directory);
  52. // 第三步:创建一个indexsearcher对象,需要指定IndexReader对象
  53. return new IndexSearcher(indexReader);
  54. }
  55. //执行查询的结果
  56. public void printResult(IndexSearcher indexSearcher,Query query)throws Exception{
  57. // 第五步:执行查询。
  58. TopDocs topDocs = indexSearcher.search(query, 10);
  59. // 第六步:返回查询结果。遍历查询结果并输出。
  60. ScoreDoc[] scoreDocs = topDocs.scoreDocs;
  61. for (ScoreDoc scoreDoc : scoreDocs) {
  62. int doc = scoreDoc.doc;
  63. Document document = indexSearcher.doc(doc);
  64. // 文件名称
  65. String fileName = document.get("fileName");
  66. System.out.println(fileName);
  67. // 文件内容
  68. String fileContent = document.get("fileContent");
  69. System.out.println(fileContent);
  70. // 文件大小
  71. String fileSize = document.get("fileSize");
  72. System.out.println(fileSize);
  73. // 文件路径
  74. String filePath = document.get("filePath");
  75. System.out.println(filePath);
  76. System.out.println("------------");
  77. }
  78. }
  79. //查询所有
  80. @Test
  81. public void testMatchAllDocsQuery() throws Exception {
  82. IndexSearcher indexSearcher = getIndexSearcher();
  83. Query query = new MatchAllDocsQuery();
  84. System.out.println(query);
  85. printResult(indexSearcher, query);
  86. //关闭资源
  87. indexSearcher.getIndexReader().close();
  88. }
  89. //根据数值范围查询
  90. @Test
  91. public void testNumericRangeQuery() throws Exception {
  92. IndexSearcher indexSearcher = getIndexSearcher();
  93. Query query = NumericRangeQuery.newLongRange("fileSize", 47L, 200L, false, true);
  94. System.out.println(query);
  95. printResult(indexSearcher, query);
  96. //关闭资源
  97. indexSearcher.getIndexReader().close();
  98. }
  99. //可以组合查询条件
  100. @Test
  101. public void testBooleanQuery() throws Exception {
  102. IndexSearcher indexSearcher = getIndexSearcher();
  103. BooleanQuery booleanQuery = new BooleanQuery();
  104. Query query1 = new TermQuery(new Term("fileName","apache"));
  105. Query query2 = new TermQuery(new Term("fileName","lucene"));
  106. // select * from user where id =1 or name = 'safdsa'
  107. booleanQuery.add(query1, Occur.MUST);
  108. booleanQuery.add(query2, Occur.SHOULD);
  109. System.out.println(booleanQuery);
  110. printResult(indexSearcher, booleanQuery);
  111. //关闭资源
  112. indexSearcher.getIndexReader().close();
  113. }
  114. //条件解释的对象查询
  115. @Test
  116. public void testQueryParser() throws Exception {
  117. IndexSearcher indexSearcher = getIndexSearcher();
  118. //参数1: 默认查询的域
  119. //参数2:采用的分析器
  120. QueryParser queryParser = new QueryParser("fileName",new IKAnalyzer());
  121. // *:* 域:值
  122. Query query = queryParser.parse("fileName:lucene is apache OR fileContent:lucene is apache");
  123. printResult(indexSearcher, query);
  124. //关闭资源
  125. indexSearcher.getIndexReader().close();
  126. }
  127. //条件解析的对象查询 多个默念域
  128. @Test
  129. public void testMultiFieldQueryParser() throws Exception {
  130. IndexSearcher indexSearcher = getIndexSearcher();
  131. String[] fields = {"fileName","fileContent"};
  132. //参数1: 默认查询的域
  133. //参数2:采用的分析器
  134. MultiFieldQueryParser queryParser = new MultiFieldQueryParser(fields,new IKAnalyzer());
  135. // *:* 域:值
  136. Query query = queryParser.parse("lucene is apache");
  137. printResult(indexSearcher, query);
  138. //关闭资源
  139. indexSearcher.getIndexReader().close();
  140. }
  141. }

以上就是lucene的基本使用方法。

solr

solr实现全文检索的流程:

  1. 配置solr服务器环境。
  2. 配置中文分析器:
  3. Schema.xml
  4. FieldType:域类型定义
  5. Field:域定义
  6. uniqueKey:组件
  7. copyField:复制域,用于当查询一个条件的时候,查询多个域。(只发起一次请求)
  8. dynamicField:动态域,用于添加一个可以动态改天域名的域,这样就可以方便我们添加域名。
  9. 安装ik分词器
  10. 设置业务系统field(域)
  11. 配置批量导入处理器

使用solr其实就是在lucene的基础上多了一些配置方法,让我们使用起来更加方便。所以,solr相应的配置起来会比较繁琐,相应的教程可以在网上搜到。

在配置好了相应的环境之后,我们可以通过自己的使用,看到solr自带的web界面的Query选项中的一些参数。熟悉一下都有什么用。

话不多说,solr的使用直接上代码吧。

  1. public class JdDaoImpl implements JdDao {
  2. // 索引库
  3. @Autowired
  4. private SolrServer solrServer;
  5. // 单机版的SolrServer
  6. // String baseURL = "127.0.0.1:8080/solr/使用的core一般默认为core1"
  7. // SolrServer 是一个抽象类,所以不能直接new它,需要知道子类的实现
  8. // SolrServer solrServer = new HttpSolrServer(baseURL)
  9. 通过上面四个条件查询对象商品结果集
  10. public List<ProductModel> selectProductModelListByQuery(String queryString, String catalog_name,
  11. String price,String sort) throws Exception {
  12. // 查询 关键词 过滤条件
  13. // 价格排序 分页 开始行 每页数 高亮 默认域 只查询指定域
  14. SolrQuery solrQuery = new SolrQuery();
  15. // 关键词
  16. solrQuery.setQuery(queryString);
  17. // 过滤条件
  18. if(null != catalog_name && !"".equals(catalog_name)){
  19. solrQuery.set("fq", "product_catalog_name:" + catalog_name);
  20. }
  21. if(null != price && !"".equals(price)){
  22. //0-9 50-*
  23. String[] p = price.split("-");
  24. solrQuery.set("fq", "product_price:[" + p[0] + " TO " + p[1] + "]");
  25. }
  26. // 价格排序
  27. if("1".equals(sort)){
  28. solrQuery.addSort("product_price", ORDER.desc);
  29. }else{
  30. solrQuery.addSort("product_price", ORDER.asc);
  31. }
  32. // 分页
  33. solrQuery.setStart(0);
  34. solrQuery.setRows(16);
  35. // 默认域
  36. solrQuery.set("df", "product_keywords");
  37. // 只查询指定域
  38. solrQuery.set("fl", "id,product_name,product_price,product_picture");
  39. // 高亮
  40. // 打开开关
  41. solrQuery.setHighlight(true);
  42. // 指定高亮域
  43. solrQuery.addHighlightField("product_name");
  44. // 前缀
  45. solrQuery.setHighlightSimplePre("<span style='color:red'>");
  46. solrQuery.setHighlightSimplePost("</span>");
  47. // 后缀
  48. // 执行查询
  49. QueryResponse response = solrServer.query(solrQuery);
  50. // 文档结果集
  51. SolrDocumentList docs = response.getResults();
  52. Map<String, Map<String, List<String>>> highlighting = response.getHighlighting();
  53. // Map K id V Map
  54. // Map K 域名 V List
  55. // List list.get(0)
  56. // 总条数
  57. long numFound = docs.getNumFound();
  58. List<ProductModel> productModels = new ArrayList<ProductModel>();
  59. for (SolrDocument doc : docs) {
  60. ProductModel productModel = new ProductModel();
  61. productModel.setPid((String) doc.get("id"));
  62. productModel.setPrice((Float) doc.get("product_price"));
  63. productModel.setPicture((String) doc.get("product_picture"));
  64. Map<String, List<String>> map = highlighting.get((String) doc.get("id"));
  65. List<String> list = map.get("product_name");
  66. productModel.setName(list.get(0));
  67. productModels.add(productModel);
  68. }
  69. return productModels;
  70. }
  71. }

solr开发常用到的jar包一般都在solr文件夹—》dist文件夹—》solr-solrj.jar和solrj-lib文件夹—》所有jar包。

我们注意一点,不要被索引的一些概念弄懵,创建索引,其实就是索引的增、删、改。查询索引就是索引的查询

发表评论

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

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

相关阅读

    相关 bash使用基础

    关于命令及命令类型 对于使用的命令BASH使用hash表,以加速下次的查找,为添加一个经常使用的命令,可以使用hash cmd BASH在执行命令时对路径中找到的同名命令