设为首页 收藏本站
查看: 1219|回复: 0

[经验分享] 一个Solr搜索实例,增删改查+高亮+分页

[复制链接]

尚未签到

发表于 2015-7-18 11:53:26 | 显示全部楼层 |阅读模式
  今天个人coding的模块测试,所以闲暇之余继续研究solr,然后顺带写了一个实例,随便搞的,solr真心不熟,期待认识热爱搜索的朋友,共同进步.
1.配置schema.xml文件[solr\collection1\conf\目录下]
  因为schema默认定义了一些Field,我们这里选取[id,title,description, author]这几个属性,将id主键type配置为string,其它几个type配置为自定义的ik分词器




DSC0000.gif
   





  Ik分词器定义如下





   







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





/**
* solrJ搜索 高亮显示
*
* @author pudongping
*
* @param server
*                     solr客户端
* @param queryString
*                     查询串
* @param pageNum
*                     分页 页码
* @param pageSize
*                     每页显示大小
* @return
*/
public static Page 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("");//渲染标签
query.setHighlightSimplePost("");//渲染标签
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 items = new ArrayList();
//查询到的记录总数
long totalRow = Long.valueOf(response.getResults().getNumFound()).intValue();
String tmpId = "";
Map 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 descList=highlightMap.get(tmpId).get("description");
List 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(pageNum, pageSize, totalRow, items);
}

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





    /**
* 根据关键字查询 [测试通过 - 使用 solr内部转换机制]
* @param
* @param server    solr客户端
* @param keyword    搜索关键字
* @param pageNum    当前页码
* @param pageSize    每页显示的大小
* @param clzz        对象类型
* @return
*/
public static Page queryHighter(SolrServer server,String solrql,
int pageNum,int pageSize,List hlField, String preTag,String postTag,Class 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 items = new ArrayList();
//查询结果集
SolrDocumentList solrDocuments = response.getResults();
try {
Object obj = null;
Method m = null;
Class fieldType = null;
Map highlightMap=response.getHighlighting();
for(SolrDocument solrDocument : solrDocuments) {
obj = clzz.newInstance();
Collection 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 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(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 lists = new ArrayList();
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 ids = new ArrayList();
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 hlFields = new ArrayList();
hlFields.add("description");
hlFields.add("keywords");
String preTag = "";
String postTag = "";
Page page = SearchEngine.queryHighter(server,solrql , 1, 10, hlFields, preTag, postTag, QzoneArticle.class, "id");
formatPrint(page, solrql);
}

//测试通过
@Test
public void qzoneCommonHLQuery(){
String solrql = "description:文字";
Page page = SearchEngine.queryComHighlight(server, solrql , 1, 10);
formatPrint(page, solrql);
}
@Test
public void qzoneQuery(){
String solrql = "文字";
Page 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 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条符合的记录.
作者:林云熙
描述:文字控,我无悔,纵是情殇离人泪
关键字:文字

作者:苏若年
描述:Java程序猿, 爱音乐,爱生活,爱文字
关键字:Java,音乐,生活,文字


运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-87962-1-1.html 上篇帖子: solr 之 datasource 下篇帖子: EasyNet.Solr 4.4.0发布及例子
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表