敬给读者的话
本文主要应用的技术是solr技术的搭建和应用,本文小编尽量写的更详细一些,让读者在不考虑项目的情况下也能正常完成solr的搭建,说完搭建之后,再说明运行solrj在项目中如何应用solr服务的。
1、solr的搭建
2、把数据库中的数据导入索引库
3、solrJ的使用
solr下载链接,内包含zookeeper、solr、tomcat,若读者只想搭建集群版,则用solr+tomcat即可。zookeeper是在搭建集群中作为集群管理者才使用的。
一、Solr服务的搭建
准备环境:
一台linux系统(小编的的IP地址192.168.25.111)
jdk安装完成。
Tomcat安装完成。
第一步:
把solr 的压缩包上传到Linux系统。
第二步:
解压solr。
tar -xvf solr-4.10.3.tgz.tgz
第三步:
安装Tomcat,解压缩即可。
第四步:
把solr部署到Tomcat下。
在 /root/solr-4.10.3/example/webapps下有solr.war包,复制到tomcat的webapps下
[root@localhost webapps]# cp solr.war /usr/local/tomcat/apache-tomcat-8.0.48/webapps/
第五步:
解压缩war包。启动Tomcat解压。关闭tomcat,然后删除solr.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。需要修改tomcat中solr工程的web.xml文件。
第九步:启动Tomcat
http://192.168.25.111:8080/solr/
至此项目就搭建完成了,接下来我们来看看界面
认识solr界面
打表示经常使用.
我们可以用文档documents增加数据,使用query查询数据。
增加的数据为json数据
id:001
title:小锋
下面我们查询一下:
q - 查询字符串。查询所有是? , 根据指定字段查询
fq - filter query 过滤查询。一般用来将查询的结果限定在某一范围,其作用类似于参数q,有时候可以被q取代。
示例(下面为q和fq都能使用的):
查询某字段为某值 type:私企 ; 查询某字段不为某值 -type:私企
查询id区间的 id:[10 TO 20]
某个开区间比如小于0的 num:[* TO 0]
某个时间段的(要满足solr日期格式 yyyy-mm-ddTHH:MM:SSZ) create_time:[2019-01-01T00:00:00Z TO 2019-01-31T23:59:59Z]
查询字段值为空、null或者不存在该字段 -field:*
sort - 排序。
示例:
age desc,id desc
fl - fieldlist 返回字段。多用于字段较多,只想关注某个字段时。
df - 默认的查询字段,一般默认指定。
wt - write type 指定输出格式。
qt - query type指定哪个类型来处理查询请求,一般不用指定,默认standarad。
indent - 返回的结果是否缩进。默认关闭。
version - 查询语法的版本。建议不使用它,有服务器指定默认值。
三、配置项目中的业务域
solr服务里有自带的业务域,但是很明显不太适合我们的项目的表(就算适合,我们也想配置一个和我们项目mysql表类似的域名称,方便查看和使用。)solr也有自带的名词解析器,这里因为我们用的中文居多,因此我们需要配置一个中文解析器(推荐使用IKAnalyzer2012FF_u1)
配置业务域在solr的配置文件中的schema.xml中定义。我们需要1、商品Id 2、商品标题 3、商品卖点 4、商品价格 5、商品图片 6、分类名称
而创建对应的业务域需要制定中文分析器。
1、创建中文解析器
创建步骤:
第一步:把中文分析器添加到工程中。
1、把IKAnalyzer2012FF_u1.jar添加到solr工程的lib目录下
2、把扩展词典、配置文件放到solr工程的WEB-INF/classes目录下。
第二步:配置一个FieldType,制定使用IKAnalyzer
修改schema.xml文件
修改Solr的schema.xml文件,添加FieldType:
<fieldType name="xiaofeng_ik" class="solr.TextField">
<analyzer class="org.wltea.analyzer.lucene.IKAnalyzer"/>
</fieldType>
第三步:配置业务域,type制定使用自定义的FieldType。
设置业务系统Field
<field name="item_title" type="xiaofeng_ik" indexed="true" stored="true"/>
<field name="item_sell_point" type="xiaofeng_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" />
<field name="item_keywords" type="xiaofeng_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"/>
第四步:重启tomcat
测试,我们写一段话测试一下中文解析器运行的如何.
可以看到很完美的展示了中文的词组信息.(当然我在mydict.dic中配置了关键词,)
你也可以试一试
四、solr在项目中的使用
众所周知,每一个商城都会有有一个搜素引擎,而搜索引擎的使用才能进一步让我们找到想要的东西,但是如果我们直接在数据库中搜索关键词的话,必须是在数据库中存在的,而且必须是连续的词语,比如数据库中有台灯这个词汇,当用户搜索台灯这个词的时候,数据库也会找到相应的产品显示出来,但是若用户搜索电灯呢?,这时候就搜索不到相应的产品了,所以此时就引出了solr在项目中的使用.当然solr是基于tomcat使用的,所以我们如果是大型项目,需要配置solrclound来更快的响应用户。我们该如何管理solr呢?于是乎就引出了solrJ。
添加文档
第一步:把solrJ的jar包添加到工程中。
第二步:创建一个SolrServer,使用HttpSolrServer创建对象。
第三步:创建一个文档对象SolrInputDocument对象。
第四步:向文档中添加域。必须有id域,域的名称必须在schema.xml中定义。
第五步:把文档添加到索引库中。
第六步:提交
测试:
HttpSolrServer和CloudSolrServer是SolrServer的子包,因此我们用他们的父类进行接收子类的对象,这样方便单机版和集群版的切换(类似nginx单机和nginx集群版),spring主需要向容器中注册HttpSolrServer或者CloudSolrServer,即可使用SolrServer。(只允许其中一个单独使用)配置文件如下:
<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">
<!--单机版solr -->
<bean id="httpSolrServer" class="org.apache.solr.client.solrj.impl.HttpSolrServer">
<constructor-arg name="baseURL" value="http://192.168.25.110:8080/solr/collection1"/>
</bean>
<!-- 集群版solrServer -->
<!-- <bean id="cloudSolrServer" class="org.apache.solr.client.solrj.impl.CloudSolrServer">
<constructor-arg index="0" value="192.168.25.110:2281,192.168.25.110:2282,192.168.25.110:2283" />
<property name="defaultCollection" value="collection1" />
</bean> -->
</beans>
不结合spring的测试类:
@Test
public void addDocument() throws Exception {
// 第一步:把solrJ的jar包添加到工程中。
// 第二步:创建一个SolrServer,使用HttpSolrServer创建对象。
SolrServer solrServer = new HttpSolrServer("http://192.168.25.154:8080/solr");
// 第三步:创建一个文档对象SolrInputDocument对象。
SolrInputDocument document = new SolrInputDocument();
// 第四步:向文档中添加域。必须有id域,域的名称必须在schema.xml中定义。
document.addField("id", "test001");
document.addField("item_title", "测试商品");
document.addField("item_price", "199");
// 第五步:把文档添加到索引库中。
solrServer.add(document);
// 第六步:提交。
solrServer.commit();
}
后台数据一键导入数据到solr服务中。
service层(solr模块):
@Autowired
private SearchMapper searchMapper;
@Autowired
private SolrServer solrServer;
@Autowired
private SolrQueryUtils solrQueryUtils;
//后台更新solr索引库
@Override
public E3Result querySearch() {
try {
//获取数据库中得所有数据
List<SearchResult> itemList = searchMapper.getItemList();
//遍历所有数据,都导入到solr服务中。
for (SearchResult searchResult : itemList)
{
SolrInputDocument document = new SolrInputDocument();
document.addField("id",searchResult.getId());
document.addField("item_title",searchResult.getTitle());
document.addField("item_sell_point",searchResult.getSell_point());
document.addField("item_price",searchResult.getPrice());
document.addField("item_image",searchResult.getImage());
document.addField("item_category_name",searchResult.getCategory_id());
solrServer.add(document);
}
//添加数据需要commit。
solrServer.commit();
//返回导入成功
return E3Result.ok();
}
catch (Exception e) {
e.printStackTrace();
return E3Result.build(500, "导入失败");
}
}
controller层(后台的controller层manager模块)
@Controller
public class SearchController {
@Autowired
private SearchService searchService;
@RequestMapping("/index/item/import")
@ResponseBody
public E3Result searchSolr() throws Exception {
return searchService.querySearch();
}
}
首页搜索引擎:默认第一页,传入数据keywords、page、
service层(solr模块)
在//首页搜索引擎
@Override
public SearchZhuResult search(String keyword, Integer page, Integer rows) throws Exception{
//创建搜索对象
SolrQuery solrQuery = new SolrQuery();
//添加默认搜索域
solrQuery.set("df", "item_title");
//添加搜索关键字
solrQuery.setQuery(keyword);
//搜索从第几个数据开始
solrQuery.setStart((page-1)*rows);
//搜索多少个数据
solrQuery.setRows(rows);
//设置高亮开启
solrQuery.setHighlight(true);
//设置高亮的返回域
solrQuery.addHighlightField("item_title");
//设置高亮的开头
solrQuery.setHighlightSimplePre("<span style='color:red;'>");
//设置高亮的结尾
solrQuery.setHighlightSimplePost("</span>");
//开始查询(自己写了一个工具类,方便查询使用)
SearchZhuResult ZhuResult = solrQueryUtils.querySolr(solrQuery);
//查询的数据有多少个
Integer count = ZhuResult.getRecourdCount();
//算出数据有多少页
int pages =(count/rows);
if (count % rows >0) {
pages++;
}
ZhuResult.setTotalPages(pages);
return ZhuResult;
}
调用的工具类:(solr模块)
package cn.tsu.search.e3mall.solr;
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.SolrServerException;
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.tsu.e3mall.pojo.SearchResult;
import cn.tsu.e3mall.pojo.SearchZhuResult;
/**
* 工具类 查询
* @author xiaofeng
*
*/
@Repository
public class SolrQueryUtils {
@Autowired
private SolrServer solrServer;
public SearchZhuResult querySolr(SolrQuery solrQuery) throws Exception{
//开始查询
QueryResponse query = solrServer.query(solrQuery);
//获取查询的list
SolrDocumentList documentList = query.getResults();
//创建一个返回对象(把数据包装进新对象中)
SearchZhuResult zhuResult = new SearchZhuResult();
//查询的数据有多少个
zhuResult.setRecourdCount((int) documentList.getNumFound());
//创建一个list大对象接收
List<SearchResult> list = new ArrayList<>();
Map<String, Map<String, List<String>>> highlighting = query.getHighlighting();
for (SolrDocument solrDocument : documentList) {
//创建List<SearchResult>中的SearchResult对象
SearchResult listitem = new SearchResult();
//向对象中存放id
listitem.setId((String) solrDocument.get("id"));
//通过id获取高亮的map集合
Map<String, List<String>> map = highlighting.get(solrDocument.get("id"));
//获取高亮的map集合中的item_title域的值
List<String> title_list = map.get("item_title");
//如果不为空,则存放高亮的数据到返回对象listitem中
if(null !=title_list && title_list.size() > 0) {
listitem.setTitle(title_list.get(0));
}else{
//否则存放不是高亮的item_title
listitem.setTitle((String) solrDocument.get("item_title"));
}
//存放其他域的值
listitem.setSell_point((String) solrDocument.get("item_sell_point"));
listitem.setCategory_id((String) solrDocument.get("item_category_name"));
listitem.setImage((String) solrDocument.get("item_image"));
listitem.setPrice((Long) solrDocument.get("item_price"));
//添加到list集合中
list.add(listitem);
}
//把list集合存放到返回对象中
zhuResult.setItemList(list);
return zhuResult;
}
}
controller层(solr模块)
package cn.tsu.search.e3mall.controller;
import org.springframework.beans.factory.annotation.Autowired;
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.tsu.e3mall.common.Commons;
import cn.tsu.e3mall.pojo.SearchZhuResult;
import cn.tsu.search.e3mall.service.SearchService;
/**
* 首页搜索引擎
* @author xiaofeng
*
*/
@Controller
public class SearchController {
@Autowired
private SearchService searchService;
@RequestMapping("/search")
public String search(String keyword,@RequestParam(defaultValue="1") Integer page,Model model) {
try {
//解决乱码
keyword= new String(keyword.getBytes("ISO-8859-1"), "UTF-8");
//调用服务层,返回搜索结果(高亮)
SearchZhuResult searchResult = searchService.search(keyword, page, Commons.SOLR_ROWS);
model.addAttribute("query", keyword);
model.addAttribute("totalPages", searchResult.getTotalPages());
model.addAttribute("page",page);
model.addAttribute("recourdCount", searchResult.getRecourdCount());
model.addAttribute("itemList", searchResult.getItemList());
return "search";
} catch (Exception e) {
e.printStackTrace();
model.addAttribute("query", "啊哦~,你搜索的不存在");
return "search";
}
}
}
本章写了又改,改了又写,写的很详细了,希望可以给您带来一些帮助,如果您有什么疑惑,欢迎评论区留言,如果我看到会及时回复大家的。。