利用solr实现商品的搜索功能
后期补充:
为什么要用solr服务,为什么要用luncence?
问题提出:当我们访问购物网站的时候,我们可以根据我们随意所想的内容输入关键字就可以查询出相关的内容,这是怎么做到呢?这些随意的数据不可能是根据数据库的字段查询的,那是怎么查询出来的呢,为什么千奇百怪的关键字都可以查询出来呢?
答案就是全文检索工具的实现,luncence采用了词元匹配和切分词。举个例子:北京天安门------luncence切分词:北京 京天 天安 安门 等等这些分词。所以我们搜索的时候都可以检索到。
有一种分词器就是IKAnalyzer中文分词器,它有细粒度切分和智能切分,即根据某种智能算法。
这就使用solr的最大的好处:检索功能的实现。
使用步骤;
(1)solr服务器搭建,因为solr是用java5开发的,所以需要jdk和tomcat。搭建部署
(2)搭建完成后,我们需要将要展示的字段引入solr的库中。配置spring与solr结合,工程启动的时候启动solr
(3)将数据库中的查询内容导入到solr索引库,这里使用的是solrj的客户端实现的。具体使用可以参考api
(4)建立搜索服务,供客户端调用。调用solr,查询内容,这中间有分页功能的实现。solr高亮显示的实现。
(5)客户端接收页面的请求参数,调用搜索服务,进行搜索。
业务字段判断标准:
1、在搜索时是否需要在此字段上进行搜索。例如:商品名称、商品的卖点、商品的描述
(这些相当于将标签给了solr,导入商品数据后,solr对这些字段的对应的商品的具体内容进行分词切分,然后,我们就可以搜索到相关内容了)
2、后续的业务是否需要用到此字段。例如:商品id。
需要用到的字段:
1、商品id
2、商品title
3、卖点
4、价格
5、商品图片
6、商品分类名称
7、商品描述
Solr中的业务字段:
1、id——》商品id
其他的对应字段创建solr的字段。
<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" /> <field name="item_desc" type="text_ik" indexed="true" stored="false" /> <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"/> <copyField source="item_desc" dest="item_keywords"/> |
重新启动tomcat
Solr 是Apache下的一个顶级开源项目,采用Java开发,它是基于Lucene的全文搜索服务器。Solr提供了比Lucene更为丰富的查询语言,同时实现了可配置、可扩展,并对索引、搜索性能进行了优化。
Solr是一个全文检索服务器,只需要进行配置就可以实现全文检索服务。有效降低频繁访问数据库对数据库造成的压力。
第一步:将solr部署在linux系统下。
第二步:solrJ是solr的客户端,使用它需要依赖solrJ的jar包。
第三步:将数据库的内容添加到solr的索引库,这样查询就在索引库查询,而不是数据库了。
controller层:
@Controller
@RequestMapping("/manager")
public class ItemController {
@Autowired
private ItemService itemService;
@RequestMapping("/importall")
@ResponseBody
public TaotaoResult importAllItem(){
TaotaoResult result= itemService.importAllItem();
return result;
}
}
service层编写:
多表查询商品,显示在页面的逻辑编写:
mapper.java
package com.taotao.search.mapper; import java.util.List; import com.taotao.search.pojo.Item; public interface ItemMapper {
List<Item> getItemList(); }
mapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.taotao.search.mapper.ItemMapper">
<select id="getItemList" resultType="com.taotao.search.pojo.Item">
SELECT
a.id,
a.title,
a.sell_point,
a.price,
a.image,
b. NAME category_name
FROM
tb_item a
LEFT JOIN tb_item_cat b ON a.cid = b.id
</select>
</mapper>
第四步:从索引库查询的逻辑编写:
//从索引库里面获取商品信息,现在这个dao层是从索引库获取信息,因为之前的写的逻辑是将db里面的数据导入到索引库。后面的查询都是从索引库中进行,而不从数据库了
@Repository
public class SearchDaoImpl implements SearchDao {
@Autowired
private SolrServer solrServer; @Override
public SearchResult search(SolrQuery query) throws Exception {
//这是从索引库里面,直接执行查询
QueryResponse response = solrServer.query(query);
//获取查询的结果
SolrDocumentList documentList= response.getResults(); SearchResult result=new SearchResult();
//这是获取总记录数
result.setRecordCount(documentList.getNumFound()); List<Item> itemList=new ArrayList<>();
//商品的高亮显示,即当鼠标移到字上时,该字体变色,这是从QueryResponse中获取的
Map<String, Map<String, List<String>>> highlighting = response.getHighlighting(); for (SolrDocument solrDocument : documentList) { //每个SolrDocument都是一个商品pojo的内容,所以这里要创建一个商品的pojo对象,来获取详细的字段
Item item=new Item();
item.setId((String) solrDocument.get("id"));
//高亮显示是title的高亮显示
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");
} item.setTitle(title);
item.setPrice((Long) solrDocument.get("item_price"));
item.setImage((String) solrDocument.get("item_image"));
item.setCategory_name((String) solrDocument.get(" item_category_name"));
item.setSell_point((String) solrDocument.get("item_sell_point"));
itemList.add(item);
} result.setItemList(itemList); return result;
} }
第五步:索引库内容建立好后,开始编写对外的服务接口,即通过条件搜索具体的商品,比如手机,会显示出总共的手机列表信息,第几页,总共多少页,总共多少个搜索结果
请求的url:
/search/query?q={查询条件}&page={page}&rows={rows}
返回的结果:TaotaoResult包装商品列表。
创建一个sql语句对应的pojo,单独建立一个pojo
用来装显示的内容列表:
public class Item {
private String id;
private String title;
private String sell_point;
private long price;
private String image;
private String category_name;
private String item_des; }
controller层:
@Controller
public class SearchController {
@Autowired
private SearchService searchService; @RequestMapping(value="/query", method=RequestMethod.GET)
@ResponseBody
public TaotaoResult search(@RequestParam("q")String queryString,
@RequestParam(defaultValue="1")Integer page,
@RequestParam(defaultValue="60")Integer rows) {
//查询条件不能为空
if (StringUtils.isBlank(queryString)) {
return TaotaoResult.build(400, "查询条件不能为空");
}
SearchResult searchResult = null;
try {
queryString = new String(queryString.getBytes("iso8859-1"), "utf-8");
searchResult = searchService.search(queryString, page, rows);
} catch (Exception e) {
e.printStackTrace();
return TaotaoResult.build(500, ExceptionUtil.getStackTrace(e));
}
return TaotaoResult.ok(searchResult); }
}
service层:利用solrJ的solrQurery来查询:
前提是要写好如何从索引库读取数据:
下面是服务的接口层编写:
controller:
@Controller
public class SearchController {
@Autowired
private SearchService searchService; @RequestMapping(value="/query", method=RequestMethod.GET)
@ResponseBody
public TaotaoResult search(@RequestParam("q")String queryString,
@RequestParam(defaultValue="1")Integer page,
@RequestParam(defaultValue="60")Integer rows) {
//查询条件不能为空
if (StringUtils.isBlank(queryString)) {
return TaotaoResult.build(400, "查询条件不能为空");
}
SearchResult searchResult = null;
try {
queryString = new String(queryString.getBytes("iso8859-1"), "utf-8");
searchResult = searchService.search(queryString, page, rows);
} catch (Exception e) {
e.printStackTrace();
return TaotaoResult.build(500, ExceptionUtil.getStackTrace(e));
}
return TaotaoResult.ok(searchResult); }
}
@Service
public class SearchServiceImpl implements SearchService {
@Autowired
private SearchDao searchDao; @Override
public SearchResult search(String queryString, int page, int rows) throws Exception {
SolrQuery query=new SolrQuery();
query.setQuery(queryString);
query.setStart((page-1)*rows);
query.setRows(rows);
//设置默认的查询搜索域,即默认的查询
query.set("df","item_keywords");
//设置高亮显示
query.setHighlight(true); query.addHighlightField("item_title");
query.setHighlightSimplePre("<em style=\"color:red\">");
query.setHighlightSimplePost("</em>");
//执行查询
SearchResult searchResult = searchDao.search(query);
//根据结果来计算商品总共多少页
long recordCount=searchResult.getRecordCount();
long pageCount=recordCount/rows;
if (recordCount % rows > 0) {
pageCount++;
}
searchResult.setPageCount(pageCount);
searchResult.setCurPage((long) page); return searchResult;
} }
客户端通过输入商品来实现搜索功能:
controller层:
@Controller
public class SearchController {
@Autowired
private SearchService searchService; @RequestMapping("/search")
public String search(@RequestParam("q")String queryString, @RequestParam(defaultValue="1")Integer page, Model model) {
if (queryString != null) {
try {
queryString = new String(queryString.getBytes("iso8859-1"), "utf-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
SearchResult searchResult = searchService.search(queryString, page);
//向页面传递参数
model.addAttribute("query", queryString);
//model.addAttribute("totalPages", searchResult.getPageCount());
model.addAttribute("itemList", searchResult.getItemList());
model.addAttribute("page", page); return "search"; }
}
service层:
@Service
public class SearchServiceImpl implements SearchService { @Value("${SEARCH_BASE_URL}")
private String SEARCH_BASE_URL; @Override
public SearchResult search(String queryString, int page) {
//这里需要的是连接+参数.这里每页显示的记录条数,可以传递也可以不用传递
// 调用taotao-search的服务
//查询参数
Map<String, String> param = new HashMap<>();
param.put("q", queryString);
param.put("page", page + "");
try {
//调用服务
String json = HttpClientUtil.doGet(SEARCH_BASE_URL, param);
//把字符串转换成java对象
TaotaoResult taotaoResult = TaotaoResult.formatToPojo(json, SearchResult.class);
SearchResult result = (SearchResult) taotaoResult.getData();
return result;
/* if (taotaoResult.getStatus() == 200) { }*/ } catch (Exception e) {
e.printStackTrace();
return null;
} } }
利用solr实现商品的搜索功能的更多相关文章
- 第04项目:淘淘商城(SpringMVC+Spring+Mybatis)【第八天】(solr服务器搭建、搜索功能实现)
https://pan.baidu.com/s/1bptYGAb#list/path=%2F&parentPath=%2Fsharelink389619878-229862621083040 ...
- 利用jquery的contains实现搜索功能
/ jquery实现的搜索功能 $('#search_btn').on('click',function(){ var txt=$('#inputValue').val(); var value=$( ...
- 商城06——solr索引库搭建&solr搜索功能实现&图片显示问题解决
1. 课程计划 1.搜索工程的搭建 2.linux下solr服务的搭建 3.Solrj使用测试 4.把数据库中的数据导入索引库 5.搜索功能的实现 2. 搜索工程搭建 要实现搜索功能,需要搭建 ...
- SSM+solr 通过商品搜索学习solr的简单使用
学习了一下https://github.com/TyCoding/ssm-redis-solr这个github上的solr搜索功能,现在来记录一下. 我的理解就是solr有点类似于数据库,但它是有索引 ...
- JAVAEE——宜立方商城07:Linux上搭建Solr服务、数据库导入索引库、搜索功能的实现
1. 学习计划 1.Solr服务搭建 2.Solrj使用测试 3.把数据库中的数据导入索引库 4.搜索功能的实现 2. Solr服务搭建 2.1. Solr的环境 Solr是java开发. 需要安装j ...
- 在ssh中利用Solr服务建立的界面化站内搜索---solr2
继上次匆匆搭建起结合solr和nutch的所谓站内搜索引擎之后,虽当时心中兴奋不已,可是看了看百度,再只能看看我的控制台的打印出每个索引项的几行文字,哦,好像差距还是有点大…… ...
- 利用SOLR搭建企业搜索平台 之——solr配置solrconfig.xml
来源:http://blog.csdn.net/zx13525079024/article/details/25310781 solrconfig.xml配置文件主要定义了SOLR的一些处理规则,包括 ...
- 利用SOLR搭建企业搜索平台 之——MultiCore
Solr Multicore 是 solr 1.3 的新特性.其目是一个solr实例,可以有多个搜索应用. 下面着手来将solr给出的一个example跑出来.这篇文章是基于<利用SOLR搭建企 ...
- 后台商品搜索功能开发SQL
在做后台的商品搜索功能开发时遇到了一些问题记录下来 版本一 <select id="SelectByNameAndParentId resultMap="Base_resul ...
随机推荐
- Vue 列表渲染及条件渲染实战
条件渲染 有时候我们要根据数据的情况,决定标签是否进行显示或者有其他动作.最常见的就是,表格渲染的时候,如果表格没有数据,就显示无数据.如果有数据就显示表格数据. Vue 帮我们提供了一个v-if的指 ...
- YQCB冲刺第二周第二天
今天的任务依然为实现查看消费明细的功能. 遇到的问题为从数据库中分类读取,实现图标的显示. 站立会议为: 任务面板为:
- mysql 修改语句及耗时
1.含有某串字母的字段替换: update imagetable set imageID = replace(imageID, 'ZH0211001', 'ZH4111001') 只要imageID含 ...
- 第二阶段每日站立会议Third Day
昨天对图片显示的大小进行调整 今天对于程序中的字体显示进行细化修改,使界面更美观 遇到的问题:当图片太小时,显示一块灰色区域,不美观
- 1001. A+B Format (20)题解
git链接 作业描述 Calculate a + b and output the sum in standard format -- that is, the digits must be sepa ...
- struts2.3.16.1+hibernate4.3.4+spring4.0.2
把之前的老项目用新的改了 发现新的有点很方便啊 Struts2+Hibernate+Spring整合 用的是 struts2.3.16.1 hibernate4.3.4 ...
- 用jar包运行带GUI的java游戏
这是从某论坛下载的java游戏demo,由于年代久远,所以没有记下出处.重要的是,这是一个带GUI的java程序. 链接: https://pan.baidu.com/s/1LjQ2bQPXvW-ti ...
- JVM面试问题
JVM主要包括:程序计数器(Program Counter),Java堆(Heap),Java虚拟机栈(Stack),本地方法栈(Native Stack),方法区(Method Area) 1.程序 ...
- debug阶段团队贡献分分配
小组名称:飞天小女警 项目名称:礼物挑选小工具 小组成员:沈柏杉(组长).程媛媛.杨钰宁.谭力铭 debug阶段各组员的贡献分分配如下: 姓名 团队贡献分 程媛媛 5.8 沈柏杉 6.5 谭力铭 3. ...
- Python入门:条件控制
条件控制其实就是if...else...(如果...条件是成立的,就做...:反之,就做...)的使用,其基本结构是: 具体看下面这个例子: def account_login(): # 定义函数 p ...