前言:
solr与Lucene的区别 :Lucene是api 需要写代码开发 ,solr是服务器,是一套基于lucence开发的全文检索框架,用就完事了。
1.1. Solr的环境
Solr是java开发。
需要安装jdk。
安装环境Linux。
需要安装Tomcat。
1.2. 搭建步骤
第一步:把solr 的压缩包上传到Linux系统
第二步:解压solr。
第三步:安装Tomcat,解压缩即可。
第四步:把solr部署到Tomcat下。
第五步:解压缩war包。启动Tomcat解压。
第六步:把/root/solr-4.10.3/example/lib/ext目录下的所有的jar包,添加到solr工程中。
[root@localhost ext]# pwd
/root/solr-4.10.3/example/lib/ext
[root@localhost ext]# cp */usr/local/solr/tomcat/webapps/solr/WEB-INF/lib/
第七步:创建一个solrhome。/example/solr目录就是一个solrhome。复制此目录到/usr/local/solr/solrhome
[root@localhost example]# pwd
/root/solr-4.10.3/example
[root@localhost example]# cp -r solr/usr/local/solr/solrhome
[root@localhost example]#
第八步:关联solr及solrhome。需要修改solr工程的web.xml文件。
第九步:启动Tomcat
http://192.168.25.154:8080/solr/
和windows下的配置完全一样。
solr客户端的一些基本操作:
清空索引:
<delete>
<query>*:*</query>
</delete>
1.3. 配置业务域
创建对应的业务域。需要制定中文分析器。
创建步骤:
第一步:把中文分析器添加到工程中。
1、把IKAnalyzer2012FF_u1.jar添加到solr工程的lib目录下
D:\software\apache-tomcat-7.0.86ForSolr\webapps\solr\WEB-INF\lib
2、把扩展词典、配置文件放到solr工程的WEB-INF/classes目录下。
第二步:配置一个FieldType,制定使用IKAnalyzer
E:\software\apache-tomcat-7.0.47ForSolr\solrhome\collection1\conf
修改schema.xml文件
修改Solr的schema.xml文件,添加FieldType:
<fieldType name="text_ik" class="solr.TextField">
<analyzer class="org.wltea.analyzer.lucene.IKAnalyzer"/>
</fieldType>
第三步:配置业务域,type制定使用自定义的FieldType。
<!--使用ik分词器-->
<field name="item_title" type="text_ik" indexed="true" stored="true"/>
<field name="item_sell_point" type="text_ik" indexed="true" stored="true"/>
<field name="item_price" type="long" indexed="true" stored="true"/>
<field name="item_image" type="string" indexed="false" stored="true" />
<field name="item_category_name" type="string" indexed="true" stored="true" />
<!--三个业务域复制到item_keywords中 方便搜索-->
<field name="item_keywords" type="text_ik" indexed="true" stored="false" multiValued="true"/>
<copyField source="item_title" dest="item_keywords"/>
<copyField source="item_sell_point" dest="item_keywords"/>
<copyField source="item_category_name" dest="item_keywords"/>
设置业务系统Field
第四步:重启tomcat
1.1.1. solrJ添加索引库
1、把solrJ的jar包添加到工程。
2、创建一个SolrServer对象。创建一个和sorl服务的连接。HttpSolrServer。
3、创建一个文档对象。SolrInputDocument。
4、向文档对象中添加域。必须有一个id域。而且文档中使用的域必须在schema.xml中定义。
5、把文档添加到索引库
6、Commit。
package cn.e3mall.solrj;
import java.util.List;
import java.util.Map;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServer;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.impl.HttpSolrServer;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.common.SolrInputDocument;
import org.junit.Test;
public class TestSolrJ {
/**
* 添加文档
* <p>Title: addDocument</p>
* <p>Description: </p>
* @throws Exception
*/
@Test
public void addDocument() throws Exception {
//创建一个SolrServer对象 创建连接 参数solr服务的url
SolrServer solrServer = new HttpSolrServer("http://192.168.25.128:8080/solr/collection1");
//创建文档对象SolrInputDocument
SolrInputDocument document =new SolrInputDocument();
//向文档对象添加域, 文档中必须包含一个id域 所有的域的名称在schema.xml中定义
document.addField("id", "doc01");
document.addField("item_title", "测试商品01");
document.addField("item_price", 1000);
//吧文档写入索引库
solrServer.add(document);
//提交
solrServer.commit();
}
/**
* 删除文档
* <p>Title: deleteDocument</p>
* <p>Description: </p>
* @throws Exception
*/
@Test
public void deleteDocument() throws Exception{
SolrServer solrServer = new HttpSolrServer("http://192.168.25.128:8080/solr/collection1");
//删除文档
// solrServer.deleteById("doc01");
//根据id删除
solrServer.deleteByQuery("id:doc01");
solrServer.commit();
}
/**
* 简答查询测试
* <p>Title: queryIndex</p>
* <p>Description: </p>
* @throws Exception
*/
@Test
public void queryIndex() throws Exception {
SolrServer solrServer =new HttpSolrServer("http://192.168.25.128:8080/solr/collection1");
SolrQuery solrQuery = new SolrQuery();
//设置执行查询
solrQuery.setQuery("*:*");
//执行查询
QueryResponse queryResponse = solrServer.query(solrQuery);
SolrDocumentList solrDocumentList = queryResponse.getResults();
System.out.println("查询结果总记录数:"+solrDocumentList.getNumFound());
for (SolrDocument solrDocument : solrDocumentList) {
System.out.println(solrDocument.get("id"));
System.out.println(solrDocument.get("item_title"));
System.out.println(solrDocument.get("item_sell_point"));
System.out.println(solrDocument.get("item_price"));
System.out.println(solrDocument.get("item_image"));
System.out.println(solrDocument.get("item_category_name"));
}
}
/**
* 复杂搜索
* @throws Exception
*/
@Test
public void queryIndexComplex() throws Exception {
SolrServer solrServer = new HttpSolrServer("http://192.168.25.128:8080/solr/collection1");
SolrQuery solrQuery = new SolrQuery();
solrQuery.setQuery("手机");
solrQuery.setStart(0);//从第几条开始
solrQuery.setRows(20);//条数
solrQuery.set("df", "item_title");
solrQuery.setHighlight(true);
//设置高亮域
solrQuery.addHighlightField("item_title");
solrQuery.setHighlightSimplePre("<em>");
solrQuery.setHighlightSimplePost("</em>");
QueryResponse queryResponse = solrServer.query(solrQuery);
SolrDocumentList solrDocumentList = queryResponse.getResults();
System.out.println(solrDocumentList.getNumFound());
Map<String, Map<String, List<String>>> highlighting = queryResponse.getHighlighting();
for (SolrDocument solrDocument : solrDocumentList) {
System.out.println(solrDocument.get("id"));
//取高亮显示
List<String> list = highlighting.get(solrDocument.get("id")).get("item_title");
String title="";
if (list!=null&&list.size()>0) {
title=list.get(0);
}else {
title=(String) solrDocument.get("item_title");
}
//有高亮内容取高亮 没有取原来标题
System.out.println(title);
System.out.println(solrDocument.get("item_sell_point"));
System.out.println(solrDocument.get("item_price"));
System.out.println(solrDocument.get("item_image"));
System.out.println(solrDocument.get("item_category_name"));
}
}
}
商品索引导入
/**
* 将商品数据导入索引库
* <p>Title: SearchItemServiceImpl</p>
* <p>Description: </p>
* <p>Company: www.itcast.cn</p>
* @version 1.0
*/
@Service
public class SearchItemServiceImpl implements SearchItemService {
@Autowired
private ItemMapper itemMapper;
@Autowired
private SolrServer solrServer;
@Override
public E3Result importItmes() {
try {
//查询商品列表
List<SearchItem> itemList = itemMapper.getItemList();
//导入索引库
for (SearchItem searchItem : itemList) {
//创建文档对象
SolrInputDocument document = new SolrInputDocument();
//向文档中添加域
document.addField("id", searchItem.getId());
document.addField("item_title", searchItem.getTitle());
document.addField("item_sell_point", searchItem.getSell_point());
document.addField("item_price", searchItem.getPrice());
document.addField("item_image", searchItem.getImage());
document.addField("item_category_name", searchItem.getCategory_name());
//写入索引库
solrServer.add(document);
}
//提交
solrServer.commit();
//返回成功
return E3Result.ok();
} catch (Exception e) {
e.printStackTrace();
return E3Result.build(500, "商品导入失败");
}
}
}
1.1.1. SolrServer的配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.2.xsd">
<bean id="httpSolrServer" class="org.apache.solr.client.solrj.impl.HttpSolrServer">
<constructor-arg index="0" value="http://192.168.25.154:8080/solr"/>
</bean>
</beans>
1.1. 解决Mapper映射文件不存在异常
<!-- 如果不添加此节点mybatis的mapper.xml文件都会被漏掉。 -->
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
1. 搜索功能实现
跟据查询条件查询索引库,返回对应的结果。
dao层:
package cn.e3mall.search.dao;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServer;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import cn.e3mall.common.pojo.SearchItem;
import cn.e3mall.common.pojo.SearchResult;
/**
* 商品搜索Dao
* <p>Title: SearchDao</p>
* <p>Description: </p>
* <p>Company: www.itcast.cn</p>
* @version 1.0
*/
@Repository
public class SearchDao {
@Autowired
private SolrServer solrServer;
public SearchResult search(SolrQuery solrQuery) throws Exception {
QueryResponse queryResponse = solrServer.query(solrQuery);
SolrDocumentList solrDocumentList = queryResponse.getResults();
long numFound = solrDocumentList.getNumFound();
SearchResult searchResult = new SearchResult();
searchResult.setRecordCount(numFound);
//取商品列表 高亮显示
Map<String, Map<String, List<String>>> highlighting = queryResponse.getHighlighting();
List<SearchItem> itemList = new ArrayList<>();
for (SolrDocument solrDocument : solrDocumentList) {
SearchItem searchItem = new SearchItem();
searchItem.setId((String)solrDocument.get("id"));
searchItem.setCategory_name((String) solrDocument.get("item_category_name"));
searchItem.setImage((String) solrDocument.get("item_image"));
searchItem.setPrice((long) solrDocument.get("item_price"));
searchItem.setSell_point((String) solrDocument.get("item_sell_point"));
List<String> list = highlighting.get(solrDocument.get("id")).get("item_title");
String title="";
if (list!=null && list.size()>0) {
title=list.get(0);
}else {
title=(String) solrDocument.get("item_title");
}
searchItem.setTitle(title);
itemList.add(searchItem);
}
searchResult.setItemList(itemList);
return searchResult;
}
}
service层
package cn.e3mall.search.service.impl;
import org.apache.solr.client.solrj.SolrQuery;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import cn.e3mall.common.pojo.SearchResult;
import cn.e3mall.search.dao.SearchDao;
import cn.e3mall.search.service.SearchService;
@Service
public class SearchServiceImpl implements SearchService {
@Autowired
private SearchDao searchDao;
@Override
public SearchResult search(String keyword, int page, int rows) throws Exception {
SolrQuery solrQuery = new SolrQuery();
solrQuery.setQuery(keyword);
if (page<=0) {
page=1;
}
solrQuery.setStart((page-1)*rows);//从第几条开始
solrQuery.setRows(rows);//条数
//设置默认搜索域
solrQuery.set("df", "item_title");
solrQuery.setHighlight(true);
solrQuery.addHighlightField("item_title");
solrQuery.setHighlightSimplePre("<em style=\"color:red\">");
solrQuery.setHighlightSimplePost("</em>");
//调用dao执行查询
SearchResult searchResult = searchDao.search(solrQuery);
long recordCount = searchResult.getRecordCount();
int totalPage = (int)(recordCount/rows);
//不足一页
if (recordCount%rows>0) {
totalPage++;
}
searchResult.setTotalPages(totalPage);
return searchResult;
}
}
service发布服务 表现层引用服务 在e3-search-web中添加接口依赖
表现层:
package cn.e3mall.search.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import cn.e3mall.common.pojo.SearchResult;
import cn.e3mall.search.service.SearchService;
/**
* 商品搜索
* <p>Title: SearchController</p>
* <p>Description: </p>
* <p>Company: www.itcast.cn</p>
* @version 1.0
*/
@Controller
public class SearchController {
@Autowired
private SearchService searchService;
@Value("${SEARCH_RESULT_ROWS}")
private Integer SEARCH_RESULT_ROWS;
@RequestMapping("/search")
public String searchItemList(String keyword,
@RequestParam(defaultValue="1")Integer page,Model model) throws Exception{
//中文乱码问题
keyword = new String(keyword.getBytes("iso-8859-1"),"utf-8");
SearchResult searchResult = searchService.search(keyword, page, SEARCH_RESULT_ROWS);
model.addAttribute("query", keyword);
model.addAttribute("totalPages", searchResult.getTotalPages());
model.addAttribute("page", page);
model.addAttribute("recourdCount", searchResult.getRecordCount());
model.addAttribute("itemList", searchResult.getItemList());
//异常测试
// int a =1/0;
return "search";
}
}