今天个人coding的模块测试,所以闲暇之余继续研究solr,然后顺带写了一个实例,随便搞的,solr真心不熟,期待认识热爱搜索的朋友,共同进步.

1.配置schema.xml文件[solr\collection1\conf\目录下]

因为schema默认定义了一些Field,我们这里选取[id,title,description, author]这几个属性,将id主键type配置为string,其它几个type配置为自定义的ik分词器

  1. <field name="id" type="string" indexed="true" stored="true" required="true" multiValued="false" />
  2. <field name="title" type="text_ik" indexed="true" stored="true" multiValued="true"/>
  3. <field name="description" type="text_ik" indexed="true" stored="true"/>
  4. <field name="author" type="text_ik" indexed="true" stored="true"/>
  5. <field name="keywords" type="text_ik" indexed="true" stored="true"/>

Ik分词器定义如下

  1. <!--定义IK分词类型-->
  2. <fieldType name="text_ik" class="solr.TextField">
  3. <!--索引时候的分词器-->
  4. <analyzer type="index" isMaxWordLength="false" class="org.wltea.analyzer.lucene.IKAnalyzer"/>
  5. <!--查询时候的分词器-->
  6. <analyzer type="query" isMaxWordLength="true" class="org.wltea.analyzer.lucene.IKAnalyzer"/>
  7. </fieldType>

2. 编写solr操作类SearchEngine.java,solrJ操作索引参看文章: http://www.cnblogs.com/dennisit/p/3623974.html3.这里演示solrj搜索高亮

  1. /**
  2. * solrJ搜索 高亮显示
  3. *
  4. * @author pudongping
  5. *
  6. * @param server
  7. * solr客户端
  8. * @param queryString
  9. * 查询串
  10. * @param pageNum
  11. * 分页 页码
  12. * @param pageSize
  13. * 每页显示大小
  14. * @return
  15. */
  16. public static Page<QzoneArticle> queryComHighlight(SolrServer server, String queryString, int pageNum,int pageSize){
  17. SolrQuery query = new SolrQuery();
  18. query.setQuery(queryString);
  19. query.setHighlight(true);//开启高亮功能
  20. query.addHighlightField("description");//高亮字段
  21. query.addHighlightField("keywords");
  22. query.setHighlightSimplePre("<font color='red'>");//渲染标签
  23. query.setHighlightSimplePost("</font>");//渲染标签
  24. query.setStart((pageNum-1)*pageSize);
  25. query.setRows(pageSize);
  26. QueryResponse response = null;
  27. try {
  28. response = server.query(query);
  29. } catch (SolrServerException e) {
  30. e.printStackTrace();
  31. return null;
  32. }
  33. //查询结果集
  34. SolrDocumentList lists = response.getResults();
  35.  
  36. //对象结果集
  37. List<QzoneArticle> items = new ArrayList<QzoneArticle>();
  38.  
  39. //查询到的记录总数
  40. long totalRow = Long.valueOf(response.getResults().getNumFound()).intValue();
  41.  
  42. String tmpId = "";
  43.  
  44. Map<String,Map<String,List<String>>> highlightMap=response.getHighlighting();
  45. for (SolrDocument solrDocument : lists) {
  46. QzoneArticle at = new QzoneArticle();
  47. tmpId=solrDocument.getFieldValue("id").toString();
  48. at.setId(tmpId);
  49. at.setAuthor(solrDocument.getFieldValue("author").toString());
  50. List<String> descList=highlightMap.get(tmpId).get("description");
  51. List<String> keywsList=highlightMap.get(tmpId).get("keywords");
  52. if(descList!=null && descList.size()>0){
  53. at.setDescription(descList.get(0));
  54. }else{
  55. //获取并设置高亮的字段title
  56. at.setDescription(solrDocument.getFieldValue("description").toString());
  57. }
  58. if(keywsList!=null && keywsList.size()>0){
  59. at.setKeywords(keywsList.get(0));
  60. }else{
  61. at.setKeywords(solrDocument.getFieldValue("keywords").toString());
  62. }
  63. items.add(at);
  64. }
  65.  
  66. //填充page对象
  67. return new Page<QzoneArticle>(pageNum, pageSize, totalRow, items);
  68.  
  69. }

搜索高亮是找到关键字所在的记录域,然后追加前后缀,重新填充到对象,这里拆开来将是两个步骤,第一步设置高亮域,第二步查询结果追加渲染标记,填充到对象.所以这个可以抽取出来写成一个公用的方法

4.抽取高亮操作,实现公用方法

  1. /**
  2. * 根据关键字查询 [测试通过 - 使用 solr内部转换机制]
  3. * @param <T>
  4. * @param server solr客户端
  5. * @param keyword 搜索关键字
  6. * @param pageNum 当前页码
  7. * @param pageSize 每页显示的大小
  8. * @param clzz 对象类型
  9. * @return
  10. */
  11. public static <T>Page<T> queryHighter(SolrServer server,String solrql,
  12. int pageNum,int pageSize,List<String> hlField, String preTag,String postTag,Class<T> clzz,String idName){
  13. SolrQuery query = new SolrQuery();
  14. query.setQuery(solrql);
  15. //设置高亮显示
  16. query.setHighlight(true);
  17. //添加高亮域
  18. for(String hlf : hlField){
  19. query.addHighlightField(hlf);
  20. }
  21. //渲染标签
  22. query.setHighlightSimplePre(preTag);
  23. query.setHighlightSimplePost(postTag);
  24. //分页查询
  25. query.setStart((pageNum-1)*pageSize);
  26. query.setRows(pageSize);
  27. QueryResponse response = null;
  28. try {
  29. response = server.query(query);
  30. } catch (SolrServerException e) {
  31. e.printStackTrace();
  32. return null;
  33. }
  34.  
  35. //查询到的记录总数
  36. long totalRow = Long.valueOf(response.getResults().getNumFound()).intValue();
  37. //查询结果集
  38. List<T> items = new ArrayList<T>();
  39.  
  40. //查询结果集
  41. SolrDocumentList solrDocuments = response.getResults();
  42. try {
  43. Object obj = null;
  44. Method m = null;
  45. Class<?> fieldType = null;
  46. Map<String,Map<String,List<String>>> highlightMap=response.getHighlighting();
  47. for(SolrDocument solrDocument : solrDocuments) {
  48. obj = clzz.newInstance();
  49. Collection<String> fieldNames = solrDocument.getFieldNames(); //得到所有的属性名
  50. for (String fieldName : fieldNames) {
  51. //需要说明的是返回的结果集中的FieldNames()比类属性多
  52. Field[] filedArrays = clzz.getDeclaredFields(); //获取类中所有属性
  53. for (Field f : filedArrays) {
  54. //如果实体属性名和查询返回集中的字段名一致,填充对应的set方法
  55. if(f.getName().equals(fieldName)){
  56.  
  57. //获取到的属性名
  58. //private java.lang.String com.test.model.Article.id
  59. f = clzz.getDeclaredField(fieldName);
  60.  
  61. //属性类型
  62. //private java.lang.String com.test.model.Article.id
  63. fieldType = f.getType();
  64.  
  65. //构造set方法名 setId
  66. String dynamicSetMethod = dynamicMethodName(f.getName(), "set");
  67.  
  68. //获取方法
  69. //public void com.test.model.Article.setId(java.lang.String)
  70. m = clzz.getMethod(dynamicSetMethod, fieldType);
  71.  
  72. //获取到的值
  73. LOG.info(f.getName() + "-->" + dynamicSetMethod+ "=" + fieldType.cast(solrDocument.getFieldValue(fieldName)));
  74.  
  75. //获取fieldType类型
  76. fieldType = getFileType(fieldType);
  77.  
  78. //获取到的属性
  79. m.invoke(obj, fieldType.cast(solrDocument.getFieldValue(fieldName)));
  80.  
  81. for(String hl : hlField){
  82. if(hl.equals(fieldName)){
  83. String idv = solrDocument.getFieldValue(idName).toString();
  84. List<String> hlfList=highlightMap.get(idv).get(fieldName);
  85. if(null!=hlfList && hlfList.size()>0){
  86. //高亮添加
  87. m.invoke(obj, fieldType.cast(hlfList.get(0)));
  88. }else{
  89. //正常添加
  90. m.invoke(obj, fieldType.cast(solrDocument.getFieldValue(fieldName)));
  91. }
  92. }
  93. }
  94.  
  95. }
  96.  
  97. }
  98.  
  99. }
  100. items.add(clzz.cast(obj));
  101. }
  102.  
  103. } catch (Exception e) {
  104. LOG.error("highlighter query error." + e.getMessage(), e);
  105. e.printStackTrace();
  106. }
  107.  
  108. //填充page对象
  109. return new Page<T>(pageNum, pageSize, totalRow, items);
  110. }
  111.  
  112. public static Class<?> getFileType(Class<?> fieldType){
  113. // 如果是 int, float等基本类型,则需要转型
  114. if (fieldType.equals(Integer.TYPE)) {
  115. return Integer.class;
  116. } else if (fieldType.equals(Float.TYPE)) {
  117. return Float.class;
  118. } else if (fieldType.equals(Double.TYPE)) {
  119. return Double.class;
  120. } else if (fieldType.equals(Boolean.TYPE)) {
  121. return Boolean.class;
  122. } else if (fieldType.equals(Short.TYPE)) {
  123. return Short.class;
  124. } else if (fieldType.equals(Long.TYPE)) {
  125. return Long.class;
  126. } else if(fieldType.equals(String.class)){
  127. return String.class;
  128. }else if(fieldType.equals(Collection.class)){
  129. return Collection.class;
  130. }
  131. return null;
  132. }

需要说明的是,这里的方法定义并不是很完善,因为反射的属性可能是一个集合,所以在利用反射转换之前,需要进行更精确地判断,这实例中实体对象中的属性为简单类型,所以这个方法可以处理.

5.junit测试

  1. package com.test.search;
  2.  
  3. import java.util.ArrayList;
  4. import java.util.List;
  5. import java.util.UUID;
  6.  
  7. import org.apache.solr.client.solrj.SolrServer;
  8. import org.junit.Before;
  9. import org.junit.Test;
  10.  
  11. import com.plugin.page.Page;
  12. import com.plugin.solr.client.SolrClient;
  13. import com.plugin.solr.engine.SolrEngineHandler;
  14. import com.test.model.QzoneArticle;
  15.  
  16. public class SolrTest {
  17.  
  18. private SolrServer server;
  19.  
  20. @Before
  21. public void init(){
  22. String solrURL = "http://localhost:8888/solr";
  23. server = SolrClient.getHttpSolrServer(solrURL);
  24. }
  25.  
  26. @Test
  27. public void qzoneAdd(){
  28. List<QzoneArticle> lists = new ArrayList<QzoneArticle>();
  29. QzoneArticle qz1 = new QzoneArticle();
  30. qz1.setId(UUID.randomUUID().toString());
  31. qz1.setAuthor("苏若年");
  32. qz1.setDescription("Java程序猿, 爱音乐,爱生活,爱文字");
  33. qz1.setKeywords("Java,音乐,生活,文字");
  34.  
  35. QzoneArticle qz2 = new QzoneArticle();
  36. qz2.setId(UUID.randomUUID().toString());
  37. qz2.setAuthor("林云熙");
  38. qz2.setDescription("文字控,我无悔,纵是情殇离人泪");
  39. qz2.setKeywords("文字");
  40.  
  41. lists.add(qz1);
  42. lists.add(qz2);
  43.  
  44. SearchEngine.addBeans(server, lists);
  45. }
  46.  
  47. @Test
  48. public void qzoneDeLId(){
  49. String id = "4f1b6b87-c824-4e38-a431-9a8f50e7af0c";
  50. SolrEngineHandler.deleteById(server, "id", id);
  51. }
  52.  
  53. @Test
  54. public void qzoneDeLIds(){
  55. List<String> ids = new ArrayList<String>();
  56. ids.add("d026e3ef-b89a-4ce2-9fbb-aa195ed2070b");
  57. ids.add("9deb98ca-5a65-424d-95ad-91e87c2bde2c");
  58. ids.add("5576650d-5517-43d5-987c-6d7135588e1f");
  59. SolrEngineHandler.deleteByIds(server, "id", ids);
  60. }
  61.  
  62. @Test
  63. public void qzoneDeLAll(){
  64. SolrEngineHandler.deleteAllIndex(server);
  65. }
  66.  
  67. @Test
  68. public void qzoneHLQuery(){
  69. String solrql = "keywords:文字";
  70. List<String> hlFields = new ArrayList<String>();
  71. hlFields.add("description");
  72. hlFields.add("keywords");
  73. String preTag = "<font color='red'>";
  74. String postTag = "</font>";
  75. Page<QzoneArticle> page = SearchEngine.queryHighter(server,solrql , 1, 10, hlFields, preTag, postTag, QzoneArticle.class, "id");
  76. formatPrint(page, solrql);
  77. }
  78.  
  79. //测试通过
  80. @Test
  81. public void qzoneCommonHLQuery(){
  82. String solrql = "description:文字";
  83. Page<QzoneArticle> page = SearchEngine.queryComHighlight(server, solrql , 1, 10);
  84. formatPrint(page, solrql);
  85. }
  86.  
  87. @Test
  88. public void qzoneQuery(){
  89. String solrql = "文字";
  90. Page<QzoneArticle> page = SearchEngine.query(server,solrql , 1, 10,QzoneArticle.class);
  91. formatPrint(page, solrql);
  92. }
  93.  
  94. @Test
  95. public void qzoneUpdate(){
  96. QzoneArticle qz = new QzoneArticle();
  97. qz.setId("5576650d-5517-43d5-987c-6d7135588e1f");
  98. qz.setAuthor("林云熙");
  99. qz.setDescription("文字控,我无悔,纵是情殇离人泪");
  100. qz.setKeywords("文字");
  101. SearchEngine.updateBean(server, qz, "id");
  102. }
  103.  
  104. @Test
  105. public void pingSolr(){
  106. System.out.println("ping solr result: " +SolrEngineHandler.ping(server));
  107. }
  108.  
  109. public void formatPrint(Page<QzoneArticle> page,String solrql){
  110. System.out.println("查询: " + solrql
  111. + "\t\t页码" + page.getPageNum()
  112. + "/" + page.getTotalPage()
  113. + ",总共找到" + page.getTotalRow()+"条符合的记录.\n");
  114.  
  115. for(QzoneArticle qz: page.getItems()){
  116. System.out.println("作者:" + qz.getAuthor());
  117. System.out.println("描述:" + qz.getDescription());
  118. System.out.println("关键字:" + qz.getKeywords() + "\n\n");
  119. }
  120. }
  121.  
  122. }

搜索结果集展示如下:

  1. 查询: keywords:文字 页码1/1,总共找到2条符合的记录.
  2.  
  3. 作者:林云熙
  4. 描述:<font color='red'>文字</font>控,我无悔,纵是情殇离人泪
  5. 关键字:<font color='red'>文字</font>
  6.  
  7. 作者:苏若年
  8. 描述:Java程序猿, 爱音乐,爱生活,爱<font color='red'>文字</font>
  9. 关键字:Java,音乐,生活,<font color='red'>文字</font>

一个Solr搜索实例,增删改查+高亮+分页的更多相关文章

  1. 自己写的一个Solr搜索实例,增删改查+高亮+分页

    今天个人coding的模块测试,所以闲暇之余继续研究solr,然后顺带写了一个实例,随便搞的,solr真心不熟,期待认识热爱搜索的朋友,共同进步. 1.配置schema.xml文件[solr\coll ...

  2. SpringBoot-Vue实现增删改查及分页小DEMO

    前言 主要通过后端 Spring Boot 技术和前端 Vue 技术来简单开发一个demo,实现增删改查.分页功能以及了解Springboot搭配vue完成前后端分离项目的开发流程. 开发栈 前端 开 ...

  3. 一个使用MVC3+NHibernate “增删改查” 的项目

    一个使用MVC3+NHibernate “增删改查” 的项目  前言: 谈到NHibernate大伙并不陌生,搞Java的更是清楚,Hibernate是一个目前应用的最广泛的开放源代码的对象关系映射框 ...

  4. 【讲义提纲】以一个实战新闻cms增删改查demo为例,给学院国创队伍培训php

    PHP实战基础——以一个新闻cms的增删改查为例 一.        环境配置 二.        数据库创建 三.        增删改查demo 连接数据库 <?php $link=mysq ...

  5. Online Coding开发模式 (通过在线配置实现一个表模型的增删改查功能,无需写任何代码)

    JEECG 智能开发平台. 开发模式由代码生成器转变为Online Coding模式                      (通过在线配置实现一个表模型的增删改查功能,无需一行代码,支持用户自定义 ...

  6. 用SpringBoot+MySql+JPA实现对数据库的增删改查和分页

    使用SpringBoot+Mysql+JPA实现对数据库的增删改查和分页      JPA是Java Persistence API的简称,中文名Java持久层API,是JDK 5.0注解或XML描述 ...

  7. SpringBoot JPA实现增删改查、分页、排序、事务操作等功能

    今天给大家介绍一下SpringBoot中JPA的一些常用操作,例如:增删改查.分页.排序.事务操作等功能.下面先来介绍一下JPA中一些常用的查询操作: //And --- 等价于 SQL 中的 and ...

  8. Magicodes.WeiChat——ASP.NET Scaffolding生成增删改查、分页、搜索、删除确认、批量操作、批量删除等业务代码

    关于T4代码生成这块,我之前写过几篇帖子,如:<Magicodes.NET框架之路——让代码再飞一会(ASP.NET Scaffolding)>(http://www.cnblogs.co ...

  9. 一个使用MVC3+NHibernate “增删改查” 的项目(修正版)

      前言: 谈到NHibernate大伙并不陌生,搞Java的更是清楚,Hibernate是一个目前应用的最广泛的开放源代码的对象关系映射框架,它对Java的JDBC(类似于ADO.Net)进行了非常 ...

随机推荐

  1. innodb 间隙锁

    innodb 间隙锁, 参考 MySQLInnoDB锁机制(二) 针对于辅助索引,也称范围索引 间隙锁只会出现在辅助索引上,唯一索引和主键索引是没有间隙锁.间隙锁(无论是S还是X)只会阻塞insert ...

  2. BZOJ2882: 工艺

    题解: 裸的字符串最小表示... 可以戳这里:http://www.cnblogs.com/ACAC/archive/2010/05/23/1742349.html 这里说一下为什么a[i+k]> ...

  3. Archlinux里面安装VMware Tools

    用虚拟机学习linux确实很方便,但是和主机的文件共享是个大问题,VMWARE TOOLS可以很好的解决这个问题,但是在ARCH里却不能向大多数linux那样方便的安装,在查了很多帖子试了无数遍之后, ...

  4. android 三目运算符 运用错误

    /************************************************************************** * android 三目运算符 运用错误 * 说 ...

  5. ↗☻【HTML5秘籍 #BOOK#】第4章 Web表单

    from元素用于组织所有表单部件,负责告诉浏览器把数据提交到哪里,方法是在action属性中提供一个URL.假如你只想在客户端使用JavaScript操作表单,那么只要在action属性中指定一个#即 ...

  6. Java [Leetcode 292]Nim Game

    问题描述: You are playing the following Nim Game with your friend: There is a heap of stones on the tabl ...

  7. Xcode7下载地址

    XCode 7 7.3.1:https://developer.apple.com/services-account/download?path=/Developer_Tools/Xcode_7.3. ...

  8. InstallShield高级应用--检查是否安装ORACLE或SQL Server

    InstallShield高级应用--检查是否安装ORACLE或SQL Server   实现原理:判断是否存在,是通过查找注册表是否含有相应标识来判断的. 注意:XP与WIN7系统注册表保存方式不一 ...

  9. codeforces 672C - Recycling Bottles 贪心水题

    感觉很简单,就是讨论一下 #include <stdio.h> #include <string.h> #include <algorithm> #include ...

  10. Solaris10下Telnet、SSH、ftp使用root登录

    学习solaris过程中,使用SecureCRT.putty等工具用root账号登录,总是登录不上去,后来经老师解答和网上找答案,发现是 solaris默认是不可以远程使用root账号登录的,如果想开 ...