Solr+java实现索引库增删改查

迈不过友情╰ 2023-10-11 10:17 109阅读 0赞

1 了解solr的配置文件

1.1 solr的核心配置文件:solrConfig.xml

solrconfig.xml 配置文件主要定义了 solr 的一些处理规则,包括索引数据的存放 位置,更新,删除,查询的一些规则配置。​ 一般此文件不需要进行修改, 采取默认即可。

(1) field标签

主要是用来指定字段名称的, Lucene中是有用户在程序中指定, solr中需要提前在配置文件中指定

  1. <field name="text" type="text_general" indexed="true" stored="false" multiValued="true"/>

name: 字段的名称
type: 字段的类型
indexed: 是否索引
stored: 是否保存
multiValued: 是否多值, 这个字段, 类似存储一个数组
这里有两个不允许删除的: 一个是 version_ 一个是 root_ 这两个是solr内部需要使用的字段
有一个字段的名称必须为id,其类型都不允许进行修改 原因是id字段已经被主键使用uniqueKey
其余的是一些初始化好的字段
在这里插入图片描述

(2)dynamicField标签 ,被称为是动态字段

  1. <dynamicField name="*_is" type="int" indexed="true" stored="true" multiValued="true"/>

此种标签是为程序的扩展所使用的, 因为我们不可能把所有的字段全部定义好, 所以就需要动态域来进行动态扩展。
在这里插入图片描述

(3)uniqueKey标签

必要标签, 表名文档的唯一属性, 一般默认为id

  1. <uniqueKey>id</uniqueKey>

在这里插入图片描述

(4)copyField标签

  1. <copyField source="cat" dest="text"/>
  2. <copyField source="dog" dest="text"/>

source: 表名要复制那个字段的值
dest: 复制到那个字段上
此种标签主要是为了查询所使用的, 例如, 当查询Text字段的时候, 实质上相当于查询title和name两个字段

(5)fieldType标签

字段类型定义标签,此种标签是用来定义字段的类型的,可以指定此字段使用何种分词器进行分词。

  1. <fieldType name="text_ik" class="solr.TextField">
  2. <analyzer class="org.wltea.analyzer.lucene.IKAnalyzer"/>
  3. </fieldType>

在这里插入图片描述

1.2 solrConfig.xml 模板

  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <schema name="example" version="1.5">
  3. <!-- 这个标签不能删除
  4. -->
  5. <field name="_version_" type="long" indexed="true" stored="true"/>
  6. <field name="_root_" type="string" indexed="true" stored="false"/>
  7. <!--不能删除
  8. -->
  9. <!--
  10. field: 指定solr的默认字段的, lucene中字段手动的定义,solr中提前定义好
  11. name : 字段的名称
  12. type : 字段的类型
  13. indexed : 是否索引(是否分词)
  14. stored : 是否保存
  15. required : 是否是必须的
  16. multiValued : 是否是多值(当前这个字段的类似是数组)
  17. id字段: id字段是文档的唯一标识, lucene中, 文档的唯一字段由lucene自己进行维护
  18. solr中, id字段需要由程序员自己进行维护, 保证id唯一, 如果不唯一, 就会将原有的数据给覆盖掉
  19. -->
  20. <field name="id" type="string" indexed="true" stored="true" required="true" multiValued="false" />
  21. <field name="name" type="text_ik" indexed="true" stored="true"/>
  22. <field name="title" type="text_ik" indexed="true" stored="true" multiValued="false"/>
  23. <field name="url" type="string" indexed="true" stored="true"/>
  24. <field name="content" type="text_ik" indexed="true" stored="true" multiValued="false"/>
  25. <field name="time" type="date" indexed="true" stored="true" multiValued="false"/>
  26. <field name="text" type="text_ik" indexed="true" stored="false" multiValued="true"/>
  27. <!--
  28. dynamicField: 动态(域)字段 , 动态域只要的目的是为了扩展新的字段而产生的
  29. -->
  30. <dynamicField name="*_i" type="text_ik" indexed="true" stored="true"/>
  31. <dynamicField name="*_is" type="text_ik" indexed="true" stored="true" multiValued="true"/>
  32. <!--
  33. uniqueKey: 指定文档的唯一字段是那个: 默认是id,建议使用id
  34. 一旦这个字段被定义成了唯一字段, 那么这个字段必须是required=true
  35. -->
  36. <uniqueKey>id</uniqueKey>
  37. <!--
  38. copyField : 复制域(字段) , 复制域主要是用来做查询
  39. 会将多个字段的数据, 复制到某一个字段上, 当用户进行查询的时候, 如果查询的复制域的字段,
  40. 那么就相当于查询了多个字段
  41. source: 来源(从哪里来)
  42. dest : 目的(到哪里去)
  43. 复制域必须是一个多值的字段
  44. -->
  45. <copyField source="title" dest="text"/>
  46. <copyField source="name" dest="text"/>
  47. <!--
  48. fieldType: 字段的类型: 定义这个类型使用哪种分词器, 使用哪种格式
  49. -->
  50. <fieldType name="string" class="solr.StrField" sortMissingLast="true" />
  51. <fieldType name="boolean" class="solr.BoolField" sortMissingLast="true"/>
  52. <fieldType name="int" class="solr.TrieIntField" precisionStep="0" positionIncrementGap="0"/>
  53. <fieldType name="float" class="solr.TrieFloatField" precisionStep="0" positionIncrementGap="0"/>
  54. <fieldType name="long" class="solr.TrieLongField" precisionStep="0" positionIncrementGap="0"/>
  55. <fieldType name="double" class="solr.TrieDoubleField" precisionStep="0" positionIncrementGap="0"/>
  56. <fieldType name="date" class="solr.TrieDateField" precisionStep="0" positionIncrementGap="0"/>
  57. <!--
  58. 配置ik分词器
  59. -->
  60. <fieldType name="text_ik" class="solr.TextField">
  61. <analyzer class="org.wltea.analyzer.lucene.IKAnalyzer"/>
  62. </fieldType>
  63. </schema>

2 引入ik分词器

2.1 导入ik相关的依赖包

放置在tomcat>webapps>solr>WEB-INF>lib下
在这里插入图片描述
导入ik相关的配置文件(ik配置文件, 扩展词典和停止词典)
将三个文件放置在tomcat>webapps>solr>WEB-INF>classes下
在这里插入图片描述

https://blog.csdn.net/weixin\_44784673/article/details/101168148

2.2 修改schema.xml配置文件

  1. <fieldType name="text_ik" class="solr.TextField">
  2. <analyzer class="org.wltea.analyzer.lucene.IKAnalyzer"/>
  3. </fieldType>

2.3 为对应的字段设置为text_ik类型

在这里插入图片描述

3 Idea操作solr

3.1 导入相关的jar包

  1. <dependency>
  2. <groupId>org.apache.solr</groupId>
  3. <artifactId>solr-solrj</artifactId>
  4. <version>4.10.2</version>
  5. </dependency>
  6. <!--日志的包, solrj执行需要一个日志包-->
  7. <dependency>
  8. <groupId>commons-logging</groupId>
  9. <artifactId>commons-logging-api</artifactId>
  10. <version>1.1</version>
  11. </dependency>

3.2 写入/修改索引库(字段名必须存在在schema.xml配置文件中)

有三种方式

  1. //方式一:原生方式
  2. @Test
  3. public void InputSorl1() throws Exception{
  4. //1. 创建solr的服务对象(发送请求, 获取数据)
  5. SolrServer solrServer = new HttpSolrServer
  6. ("http://localhost:8080/solr/collection1");
  7. //2. 添加索引
  8. /*name的字段名必须存在,配置在schema.xml*/
  9. List<SolrInputDocument> docs = new ArrayList<SolrInputDocument>();
  10. SolrInputDocument doc = new SolrInputDocument();
  11. doc.addField("id","2");
  12. doc.addField("title","双十一来了");
  13. doc.addField("content","又到了卖肾的季节了");
  14. docs.add(doc);
  15. SolrInputDocument doc1 = new SolrInputDocument();
  16. doc1.addField("id","3");
  17. doc1.addField("title","剁手节来了");
  18. doc1.addField("content","今天你剁手了吗?");
  19. docs.add(doc1);
  20. solrServer.add(docs);
  21. //3. 提交数据
  22. solrServer.commit();
  23. }
  24. //方式二:一次写入多条索引
  25. @Test
  26. public void InputSorl2() throws Exception {
  27. //1. 创建solrServer对象
  28. SolrServer solrServer = new HttpSolrServer("http://localhost:8080/solr/collection1");
  29. //2.1 设置多条数据
  30. List<SolrInputDocument> docs = new ArrayList<>();
  31. for(int i=0 ; i<10 ; i++){
  32. //2.1.1 创建一个document
  33. SolrInputDocument document = new SolrInputDocument();
  34. document.addField("id",i);
  35. document.addField("content","solr是一个独立的企业级搜索应用服务器, 可以通过http请求访问这个服务器, 获取或者写入对应的内容, 其底层是Lucene "+i);
  36. document.addField("title","solr的简介");
  37. //2.1.2 将document添加到集合中
  38. docs.add(document);
  39. }
  40. //2. 写入索引
  41. solrServer.add(docs);
  42. //3. 提交索引
  43. solrServer.commit();
  44. }
  45. //方式三:使用javaBean来添加索引数据
  46. @Test
  47. public void InputSorl3() throws Exception {
  48. //1. 创建 solr的服务对象
  49. SolrServer solrServer = new HttpSolrServer("http://localhost:8080/solr/collection1");
  50. //2. 添加文档数据
  51. News news = new News
  52. ("3","Ella老公被曝呛声片场工作人员:我有的是钱","就怕因此拍摄不顺或当机,赖斯翔虽听从规劝,却也反呛","http://ent.163.com/18/1107/10/E00KM09000038FO9.html");
  53. solrServer.addBean(news);
  54. // 使用addBeans来添加多条数据
  55. //3. 提交数据
  56. solrServer.commit();
  57. }

3.3 删除索引库

  1. @Test
  2. public void delIndex() throws Exception {
  3. //1. 创建 solr的服务对象
  4. SolrServer solrServer = new HttpSolrServer("http://localhost:8080/solr/collection1");
  5. //2. 执行删除
  6. //solrServer.deleteByQuery("*:*"); //删除全部的数据
  7. solrServer.deleteById("1");
  8. //3. 提交数据
  9. solrServer.commit();
  10. }

3.4 查询索引库

1. 基本查询

  1. //查询全部
  2. @Test
  3. public void indexSearcherSolrTest01() throws Exception {
  4. //1. 创建 solrServer对象
  5. SolrServer solrServer = new HttpSolrServer("http://localhost:8080/solr/collection1");
  6. //2. 执行查询
  7. //SolrQuery : solr的查询对象
  8. SolrQuery solrQuery = new SolrQuery("*:*");
  9. QueryResponse response = solrServer.query(solrQuery);
  10. //3. 获取数据
  11. SolrDocumentList documentList = response.getResults();
  12. for (SolrDocument document : documentList) {
  13. String id = (String) document.get("id");
  14. String title = (String) document.get("title");
  15. String content = (String) document.get("content");
  16. String url = (String) document.get("url");
  17. System.out.println("id "+id+" title"+title+" content"+content+" url"+url);
  18. }
  19. }
  20. //查询对象
  21. @Test
  22. public void indexSearcherSolrTest02() throws Exception {
  23. //1. 创建 solrServer对象
  24. SolrServer solrServer = new HttpSolrServer("http://localhost:8080/solr/collection1");
  25. //2. 执行查询
  26. //SolrQuery : solr的查询对象
  27. SolrQuery solrQuery = new SolrQuery("*:*");
  28. QueryResponse response = solrServer.query(solrQuery);
  29. //3. 获取数据 : 此处有可能会出现转换类型异常的错误:
  30. List<News> newsList = response.getBeans(News.class);
  31. for (News news : newsList) {
  32. System.out.println(news.getId()+" "+news.getTitle());
  33. }
  34. }

2. 复杂查询

  1. //服务对象
  2. public void query(SolrQuery query) throws Exception{
  3. //创建SolrServer服务对象
  4. SolrServer server = new HttpSolrServer("http://localhost:8080/solr/collection1");
  5. //创建Solr的查询对象
  6. QueryResponse response = server.query(query);
  7. //文档的集合
  8. SolrDocumentList documentList = response.getResults();
  9. for (SolrDocument document : documentList) {
  10. String id = document.get("id").toString();
  11. String title = document.get("title").toString();
  12. System.out.println("id:"+id+";title:"+title);
  13. }
  14. }
  15. //词条查询
  16. @Test
  17. public void testTerm() throws Exception{
  18. /*
  19. * 字段名:关键字
  20. * 在查询时,会对关键字进行分词
  21. *
  22. * */
  23. SolrQuery query = new SolrQuery("title:钱");
  24. query(query);
  25. }
  26. //通配符查询
  27. @Test
  28. public void testWildCard() throws Exception{
  29. /*
  30. * *:匹配0到多个字符
  31. * ?:匹配1个字符
  32. *
  33. * */
  34. SolrQuery query = new SolrQuery("title:selin*");
  35. query(query);
  36. }
  37. //模糊查询
  38. @Test
  39. public void testFuzzy() throws Exception{
  40. /*
  41. * 在关键字之后添加~,表示进行模糊查询
  42. *
  43. * 最大编辑次数:通过新增,修改,删除可以匹配正确的词条的次数,默认为2
  44. *
  45. * ~后的数据,表示最大的编辑次数
  46. * */
  47. SolrQuery query = new SolrQuery("title:selinaq~1");
  48. query(query);
  49. }
  50. //范围查找查询
  51. @Test
  52. public void testRange() throws Exception{
  53. /*
  54. *
  55. *
  56. * */
  57. //SolrQuery query = new SolrQuery("id:[20 TO 50]");
  58. SolrQuery query = new SolrQuery("publishTime:{2001-01-01T12:00:00Z TO 2019-01-01T12:00:00Z}");
  59. query(query);
  60. }
  61. //组合
  62. @Test
  63. public void testBoolean() throws Exception{
  64. /*
  65. * AND
  66. * OR
  67. * NOT
  68. *
  69. * */
  70. //SolrQuery query = new SolrQuery("id:[20 TO 50]");
  71. SolrQuery query = new SolrQuery(" title:xxx or inrot:xxx");
  72. query(query);
  73. }

4 solr的高级使用

4.1 solr的排序

  1. @Test
  2. public void sortTest() throws Exception {
  3. SolrQuery solrQuery = new SolrQuery("*:*");
  4. solrQuery.setSort("id", SolrQuery.ORDER.asc);
  5. publicSearch(solrQuery);
  6. }

4.2 solr的分页

  1. @Test
  2. public void limitTest() throws Exception {
  3. int page = 2; //当前页
  4. int pageSize = 3 ;// 每页条数
  5. SolrQuery solrQuery = new SolrQuery("*:*");
  6. // 排序
  7. solrQuery.setSort("id", SolrQuery.ORDER.asc);
  8. //分页
  9. solrQuery.setStart((page-1)*pageSize);
  10. solrQuery.setRows(pageSize);
  11. publicSearch(solrQuery);
  12. }

4.3 solr 的高亮

  1. @Test
  2. public void highlighterTest() throws Exception {
  3. //1. 创建solr的服务对象
  4. SolrServer solrServer = new HttpSolrServer("http://localhost:8080/solr/collection1");
  5. int page = 1; //当前页
  6. int pageSize = 3 ;// 每页条数
  7. SolrQuery solrQuery = new SolrQuery("content:lucene");
  8. // 排序
  9. solrQuery.setSort("id", SolrQuery.ORDER.asc);
  10. //分页
  11. solrQuery.setStart((page-1)*pageSize);
  12. solrQuery.setRows(pageSize);
  13. //高亮:
  14. solrQuery.setHighlight(true); //开启了高亮
  15. solrQuery.addHighlightField("content"); //使用add方法来设置高亮字段, 说明高亮字段可以有多个
  16. solrQuery.addHighlightField("title");
  17. solrQuery.setHighlightSimplePre("<font color='red'>");
  18. solrQuery.setHighlightSimplePost("</font>");
  19. //2. 执行查询
  20. QueryResponse response = solrServer.query(solrQuery);
  21. /*
  22. 最外层的map:
  23. key: 文档的id
  24. value: 文档的高亮内容
  25. 内层的map:
  26. key: 高亮的字段
  27. value: 这个字段的高亮内容
  28. list集合: 高亮内容, 而且集合中一般只有一个数据, 除非高亮的字段是一个多值的字段,并且设置高亮的最大分片数大于1
  29. */
  30. Map<String, Map<String, List<String>>> map = response.getHighlighting();
  31. for (String docId : map.keySet()) {
  32. Map<String, List<String>> listMap = map.get(docId);
  33. for (String filed : listMap.keySet()) {
  34. List<String> list = listMap.get(filed);
  35. System.out.println(list.get(0)+" "+list.size());
  36. }
  37. }
  38. }

发表评论

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

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

相关阅读