今天个人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搜索实例,增删改查+高亮+分页的更多相关文章

  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. c语言变量名称与变量

    0x00030 , 0x00031 ,0x00032 ,0x00033 是四个字节,用来存放0x00010(字母a的地址)

  2. 【 D3.js 高级系列 — 3.0 】 堆栈图

    堆栈图布局(Stack Layout)能够计算二维数组每一数据层的基线,以方便将各数据层叠加起来.本文讲解堆栈图的制作方法. 先说说什么是堆栈图. 例如,有如下情况: 某公司,销售三种产品:个人电脑. ...

  3. [转] ArcEngine中打开各种数据源(WorkSpace)的连接

    原文 ArcEngine中打开各种数据源(WorkSpace)的连接(SDE.personal/File.ShapeFile.CAD数据.影像图.影像数据集) ArcEngine 可以接受多种数据源. ...

  4. Spring注释@Qualifier

    在学习@Autowired的时候我们已经接触到了@Qualifier, 这节就来详细学习一下自定义@Qualifier. 例如定义一个交通工具类:Vehicle,以及它的子类Bus和Sedan. 如果 ...

  5. 《深入Java虚拟机学习笔记》- 第1章 Java体系结构

    一.体系结构组成 当编写并运行一个Java程序时,就同时体验了这四种技术.用Java语言编写源代码,编译成Java Class文件,然后再在Java虚拟机上运行class文件.当编写程序时,通过调用类 ...

  6. HDU 2121 Ice_cream’s world II 最小树形图

    这个题就是需要求整个有向带权图的最小树形图,没有指定根,那就需要加一个虚根 这个虚根到每个点的权值是总权值+1,然后就可以求了,如果求出来的权值大于等于二倍的总权值,就无解 有解的情况,还需要输出最根 ...

  7. [King.yue]Ext.net 页面布局Flex

    此属性仅当父布局HboxLayout或使用VboxLayout.此配置选项被应用到子项目容器管理的布局.每个子项目以Flex属性被弯曲的水平根据每个项目的相对弹性值比较,都带有一个弯曲值指定项目金额. ...

  8. [selenium webdriver Java]显示的等待同步

    显示等待可以在执行下一次操作时,自定义等待条件 显示的等待只需要执行在需要同步的地方而不影响脚本的其他地方 Selenium WebDriver提供了WebDriverWait和ExpectedCon ...

  9. Anti-Grain Geometry 概述

    AGG是一个轻量.灵活.可靠的图形算法库,AGG各部分之间是松耦合的,也即是说各部分可以单独使用. The primary goal of Anti-Grain Geometry is to brea ...

  10. IoSkipCurrentIrpStackLocation .(转)

    原文链接:http://m.blog.csdn.net/blog/ruanben/19758769# 当驱动被分层以后,他们被注册到一个chain中,IRP会在这个chain中传递,从最上面,到最下面 ...