一个Solr搜索实例,增删改查+高亮+分页
今天个人coding的模块测试,所以闲暇之余继续研究solr,然后顺带写了一个实例,随便搞的,solr真心不熟,期待认识热爱搜索的朋友,共同进步.
1.配置schema.xml文件[solr\collection1\conf\目录下]
因为schema默认定义了一些Field,我们这里选取[id,title,description, author]这几个属性,将id主键type配置为string,其它几个type配置为自定义的ik分词器

- <field name="id" type="string" indexed="true" stored="true" required="true" multiValued="false" />
- <field name="title" type="text_ik" indexed="true" stored="true" multiValued="true"/>
- <field name="description" type="text_ik" indexed="true" stored="true"/>
- <field name="author" type="text_ik" indexed="true" stored="true"/>
- <field name="keywords" type="text_ik" indexed="true" stored="true"/>

Ik分词器定义如下

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

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

- /**
- * solrJ搜索 高亮显示
- *
- * @author pudongping
- *
- * @param server
- * solr客户端
- * @param queryString
- * 查询串
- * @param pageNum
- * 分页 页码
- * @param pageSize
- * 每页显示大小
- * @return
- */
- public static Page<QzoneArticle> queryComHighlight(SolrServer server, String queryString, int pageNum,int pageSize){
- SolrQuery query = new SolrQuery();
- query.setQuery(queryString);
- query.setHighlight(true);//开启高亮功能
- query.addHighlightField("description");//高亮字段
- query.addHighlightField("keywords");
- query.setHighlightSimplePre("<font color='red'>");//渲染标签
- query.setHighlightSimplePost("</font>");//渲染标签
- query.setStart((pageNum-1)*pageSize);
- query.setRows(pageSize);
- QueryResponse response = null;
- try {
- response = server.query(query);
- } catch (SolrServerException e) {
- e.printStackTrace();
- return null;
- }
- //查询结果集
- SolrDocumentList lists = response.getResults();
- //对象结果集
- List<QzoneArticle> items = new ArrayList<QzoneArticle>();
- //查询到的记录总数
- long totalRow = Long.valueOf(response.getResults().getNumFound()).intValue();
- String tmpId = "";
- Map<String,Map<String,List<String>>> highlightMap=response.getHighlighting();
- for (SolrDocument solrDocument : lists) {
- QzoneArticle at = new QzoneArticle();
- tmpId=solrDocument.getFieldValue("id").toString();
- at.setId(tmpId);
- at.setAuthor(solrDocument.getFieldValue("author").toString());
- List<String> descList=highlightMap.get(tmpId).get("description");
- List<String> keywsList=highlightMap.get(tmpId).get("keywords");
- if(descList!=null && descList.size()>0){
- at.setDescription(descList.get(0));
- }else{
- //获取并设置高亮的字段title
- at.setDescription(solrDocument.getFieldValue("description").toString());
- }
- if(keywsList!=null && keywsList.size()>0){
- at.setKeywords(keywsList.get(0));
- }else{
- at.setKeywords(solrDocument.getFieldValue("keywords").toString());
- }
- items.add(at);
- }
- //填充page对象
- return new Page<QzoneArticle>(pageNum, pageSize, totalRow, items);
- }

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

- /**
- * 根据关键字查询 [测试通过 - 使用 solr内部转换机制]
- * @param <T>
- * @param server solr客户端
- * @param keyword 搜索关键字
- * @param pageNum 当前页码
- * @param pageSize 每页显示的大小
- * @param clzz 对象类型
- * @return
- */
- public static <T>Page<T> queryHighter(SolrServer server,String solrql,
- int pageNum,int pageSize,List<String> hlField, String preTag,String postTag,Class<T> clzz,String idName){
- SolrQuery query = new SolrQuery();
- query.setQuery(solrql);
- //设置高亮显示
- query.setHighlight(true);
- //添加高亮域
- for(String hlf : hlField){
- query.addHighlightField(hlf);
- }
- //渲染标签
- query.setHighlightSimplePre(preTag);
- query.setHighlightSimplePost(postTag);
- //分页查询
- query.setStart((pageNum-1)*pageSize);
- query.setRows(pageSize);
- QueryResponse response = null;
- try {
- response = server.query(query);
- } catch (SolrServerException e) {
- e.printStackTrace();
- return null;
- }
- //查询到的记录总数
- long totalRow = Long.valueOf(response.getResults().getNumFound()).intValue();
- //查询结果集
- List<T> items = new ArrayList<T>();
- //查询结果集
- SolrDocumentList solrDocuments = response.getResults();
- try {
- Object obj = null;
- Method m = null;
- Class<?> fieldType = null;
- Map<String,Map<String,List<String>>> highlightMap=response.getHighlighting();
- for(SolrDocument solrDocument : solrDocuments) {
- obj = clzz.newInstance();
- Collection<String> fieldNames = solrDocument.getFieldNames(); //得到所有的属性名
- for (String fieldName : fieldNames) {
- //需要说明的是返回的结果集中的FieldNames()比类属性多
- Field[] filedArrays = clzz.getDeclaredFields(); //获取类中所有属性
- for (Field f : filedArrays) {
- //如果实体属性名和查询返回集中的字段名一致,填充对应的set方法
- if(f.getName().equals(fieldName)){
- //获取到的属性名
- //private java.lang.String com.test.model.Article.id
- f = clzz.getDeclaredField(fieldName);
- //属性类型
- //private java.lang.String com.test.model.Article.id
- fieldType = f.getType();
- //构造set方法名 setId
- String dynamicSetMethod = dynamicMethodName(f.getName(), "set");
- //获取方法
- //public void com.test.model.Article.setId(java.lang.String)
- m = clzz.getMethod(dynamicSetMethod, fieldType);
- //获取到的值
- LOG.info(f.getName() + "-->" + dynamicSetMethod+ "=" + fieldType.cast(solrDocument.getFieldValue(fieldName)));
- //获取fieldType类型
- fieldType = getFileType(fieldType);
- //获取到的属性
- m.invoke(obj, fieldType.cast(solrDocument.getFieldValue(fieldName)));
- for(String hl : hlField){
- if(hl.equals(fieldName)){
- String idv = solrDocument.getFieldValue(idName).toString();
- List<String> hlfList=highlightMap.get(idv).get(fieldName);
- if(null!=hlfList && hlfList.size()>0){
- //高亮添加
- m.invoke(obj, fieldType.cast(hlfList.get(0)));
- }else{
- //正常添加
- m.invoke(obj, fieldType.cast(solrDocument.getFieldValue(fieldName)));
- }
- }
- }
- }
- }
- }
- items.add(clzz.cast(obj));
- }
- } catch (Exception e) {
- LOG.error("highlighter query error." + e.getMessage(), e);
- e.printStackTrace();
- }
- //填充page对象
- return new Page<T>(pageNum, pageSize, totalRow, items);
- }
- public static Class<?> getFileType(Class<?> fieldType){
- // 如果是 int, float等基本类型,则需要转型
- if (fieldType.equals(Integer.TYPE)) {
- return Integer.class;
- } else if (fieldType.equals(Float.TYPE)) {
- return Float.class;
- } else if (fieldType.equals(Double.TYPE)) {
- return Double.class;
- } else if (fieldType.equals(Boolean.TYPE)) {
- return Boolean.class;
- } else if (fieldType.equals(Short.TYPE)) {
- return Short.class;
- } else if (fieldType.equals(Long.TYPE)) {
- return Long.class;
- } else if(fieldType.equals(String.class)){
- return String.class;
- }else if(fieldType.equals(Collection.class)){
- return Collection.class;
- }
- return null;
- }

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

- package com.test.search;
- import java.util.ArrayList;
- import java.util.List;
- import java.util.UUID;
- import org.apache.solr.client.solrj.SolrServer;
- import org.junit.Before;
- import org.junit.Test;
- import com.plugin.page.Page;
- import com.plugin.solr.client.SolrClient;
- import com.plugin.solr.engine.SolrEngineHandler;
- import com.test.model.QzoneArticle;
- public class SolrTest {
- private SolrServer server;
- @Before
- public void init(){
- String solrURL = "http://localhost:8888/solr";
- server = SolrClient.getHttpSolrServer(solrURL);
- }
- @Test
- public void qzoneAdd(){
- List<QzoneArticle> lists = new ArrayList<QzoneArticle>();
- QzoneArticle qz1 = new QzoneArticle();
- qz1.setId(UUID.randomUUID().toString());
- qz1.setAuthor("苏若年");
- qz1.setDescription("Java程序猿, 爱音乐,爱生活,爱文字");
- qz1.setKeywords("Java,音乐,生活,文字");
- QzoneArticle qz2 = new QzoneArticle();
- qz2.setId(UUID.randomUUID().toString());
- qz2.setAuthor("林云熙");
- qz2.setDescription("文字控,我无悔,纵是情殇离人泪");
- qz2.setKeywords("文字");
- lists.add(qz1);
- lists.add(qz2);
- SearchEngine.addBeans(server, lists);
- }
- @Test
- public void qzoneDeLId(){
- String id = "4f1b6b87-c824-4e38-a431-9a8f50e7af0c";
- SolrEngineHandler.deleteById(server, "id", id);
- }
- @Test
- public void qzoneDeLIds(){
- List<String> ids = new ArrayList<String>();
- ids.add("d026e3ef-b89a-4ce2-9fbb-aa195ed2070b");
- ids.add("9deb98ca-5a65-424d-95ad-91e87c2bde2c");
- ids.add("5576650d-5517-43d5-987c-6d7135588e1f");
- SolrEngineHandler.deleteByIds(server, "id", ids);
- }
- @Test
- public void qzoneDeLAll(){
- SolrEngineHandler.deleteAllIndex(server);
- }
- @Test
- public void qzoneHLQuery(){
- String solrql = "keywords:文字";
- List<String> hlFields = new ArrayList<String>();
- hlFields.add("description");
- hlFields.add("keywords");
- String preTag = "<font color='red'>";
- String postTag = "</font>";
- Page<QzoneArticle> page = SearchEngine.queryHighter(server,solrql , 1, 10, hlFields, preTag, postTag, QzoneArticle.class, "id");
- formatPrint(page, solrql);
- }
- //测试通过
- @Test
- public void qzoneCommonHLQuery(){
- String solrql = "description:文字";
- Page<QzoneArticle> page = SearchEngine.queryComHighlight(server, solrql , 1, 10);
- formatPrint(page, solrql);
- }
- @Test
- public void qzoneQuery(){
- String solrql = "文字";
- Page<QzoneArticle> page = SearchEngine.query(server,solrql , 1, 10,QzoneArticle.class);
- formatPrint(page, solrql);
- }
- @Test
- public void qzoneUpdate(){
- QzoneArticle qz = new QzoneArticle();
- qz.setId("5576650d-5517-43d5-987c-6d7135588e1f");
- qz.setAuthor("林云熙");
- qz.setDescription("文字控,我无悔,纵是情殇离人泪");
- qz.setKeywords("文字");
- SearchEngine.updateBean(server, qz, "id");
- }
- @Test
- public void pingSolr(){
- System.out.println("ping solr result: " +SolrEngineHandler.ping(server));
- }
- public void formatPrint(Page<QzoneArticle> page,String solrql){
- System.out.println("查询: " + solrql
- + "\t\t页码" + page.getPageNum()
- + "/" + page.getTotalPage()
- + ",总共找到" + page.getTotalRow()+"条符合的记录.\n");
- for(QzoneArticle qz: page.getItems()){
- System.out.println("作者:" + qz.getAuthor());
- System.out.println("描述:" + qz.getDescription());
- System.out.println("关键字:" + qz.getKeywords() + "\n\n");
- }
- }
- }

搜索结果集展示如下:

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

一个Solr搜索实例,增删改查+高亮+分页的更多相关文章
- 自己写的一个Solr搜索实例,增删改查+高亮+分页
今天个人coding的模块测试,所以闲暇之余继续研究solr,然后顺带写了一个实例,随便搞的,solr真心不熟,期待认识热爱搜索的朋友,共同进步. 1.配置schema.xml文件[solr\coll ...
- SpringBoot-Vue实现增删改查及分页小DEMO
前言 主要通过后端 Spring Boot 技术和前端 Vue 技术来简单开发一个demo,实现增删改查.分页功能以及了解Springboot搭配vue完成前后端分离项目的开发流程. 开发栈 前端 开 ...
- 一个使用MVC3+NHibernate “增删改查” 的项目
一个使用MVC3+NHibernate “增删改查” 的项目 前言: 谈到NHibernate大伙并不陌生,搞Java的更是清楚,Hibernate是一个目前应用的最广泛的开放源代码的对象关系映射框 ...
- 【讲义提纲】以一个实战新闻cms增删改查demo为例,给学院国创队伍培训php
PHP实战基础——以一个新闻cms的增删改查为例 一. 环境配置 二. 数据库创建 三. 增删改查demo 连接数据库 <?php $link=mysq ...
- Online Coding开发模式 (通过在线配置实现一个表模型的增删改查功能,无需写任何代码)
JEECG 智能开发平台. 开发模式由代码生成器转变为Online Coding模式 (通过在线配置实现一个表模型的增删改查功能,无需一行代码,支持用户自定义 ...
- 用SpringBoot+MySql+JPA实现对数据库的增删改查和分页
使用SpringBoot+Mysql+JPA实现对数据库的增删改查和分页 JPA是Java Persistence API的简称,中文名Java持久层API,是JDK 5.0注解或XML描述 ...
- SpringBoot JPA实现增删改查、分页、排序、事务操作等功能
今天给大家介绍一下SpringBoot中JPA的一些常用操作,例如:增删改查.分页.排序.事务操作等功能.下面先来介绍一下JPA中一些常用的查询操作: //And --- 等价于 SQL 中的 and ...
- Magicodes.WeiChat——ASP.NET Scaffolding生成增删改查、分页、搜索、删除确认、批量操作、批量删除等业务代码
关于T4代码生成这块,我之前写过几篇帖子,如:<Magicodes.NET框架之路——让代码再飞一会(ASP.NET Scaffolding)>(http://www.cnblogs.co ...
- 一个使用MVC3+NHibernate “增删改查” 的项目(修正版)
前言: 谈到NHibernate大伙并不陌生,搞Java的更是清楚,Hibernate是一个目前应用的最广泛的开放源代码的对象关系映射框架,它对Java的JDBC(类似于ADO.Net)进行了非常 ...
随机推荐
- innodb 间隙锁
innodb 间隙锁, 参考 MySQLInnoDB锁机制(二) 针对于辅助索引,也称范围索引 间隙锁只会出现在辅助索引上,唯一索引和主键索引是没有间隙锁.间隙锁(无论是S还是X)只会阻塞insert ...
- BZOJ2882: 工艺
题解: 裸的字符串最小表示... 可以戳这里:http://www.cnblogs.com/ACAC/archive/2010/05/23/1742349.html 这里说一下为什么a[i+k]> ...
- Archlinux里面安装VMware Tools
用虚拟机学习linux确实很方便,但是和主机的文件共享是个大问题,VMWARE TOOLS可以很好的解决这个问题,但是在ARCH里却不能向大多数linux那样方便的安装,在查了很多帖子试了无数遍之后, ...
- android 三目运算符 运用错误
/************************************************************************** * android 三目运算符 运用错误 * 说 ...
- ↗☻【HTML5秘籍 #BOOK#】第4章 Web表单
from元素用于组织所有表单部件,负责告诉浏览器把数据提交到哪里,方法是在action属性中提供一个URL.假如你只想在客户端使用JavaScript操作表单,那么只要在action属性中指定一个#即 ...
- Java [Leetcode 292]Nim Game
问题描述: You are playing the following Nim Game with your friend: There is a heap of stones on the tabl ...
- Xcode7下载地址
XCode 7 7.3.1:https://developer.apple.com/services-account/download?path=/Developer_Tools/Xcode_7.3. ...
- InstallShield高级应用--检查是否安装ORACLE或SQL Server
InstallShield高级应用--检查是否安装ORACLE或SQL Server 实现原理:判断是否存在,是通过查找注册表是否含有相应标识来判断的. 注意:XP与WIN7系统注册表保存方式不一 ...
- codeforces 672C - Recycling Bottles 贪心水题
感觉很简单,就是讨论一下 #include <stdio.h> #include <string.h> #include <algorithm> #include ...
- Solaris10下Telnet、SSH、ftp使用root登录
学习solaris过程中,使用SecureCRT.putty等工具用root账号登录,总是登录不上去,后来经老师解答和网上找答案,发现是 solaris默认是不可以远程使用root账号登录的,如果想开 ...