- . -
面试题-利用solr实现商品的搜索功能
问题提出:当我们访问购物的时候,我们可以根据我们随意所想的内容输入关键字就可以查询出相关的内容,这是怎么做到呢?这些随意的数据不可能是根据数据库的字段查询的,那是怎么查询出来的呢,为什么千奇百怪的关键字都可以查询出来呢?
答案就是全文检索工具的实现,luncence采用了词元匹配和切分词。举个例子:天安门------luncence切分词: 京天 天安 安门 等等这些分词。所以我们搜索的时候都可以检索到。
有一种分词器就是ik中文分词器,它有细粒度切分和智能切分,即根据某种智能算法。这就使用solr的最大的好处:检索功能的实现。
使用步骤;(1)solr服务器搭建,因为solr是用java5开发的,所以需要jdk和tomcat。搭建部署(2)搭建完成后,我们需要将要展示的字段引入solr的库中。配置sring与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的字段。
[AppleScript] 纯文本查看复制代码
?
- . .考试资料 - . - 09 10 name=\ 12 13 重新启动tomcatSolr 是Apache下的一个顶级开源项目,采用Java开发,它是基于Lucene的全文搜索服务器。Solr提供了比Lucene更为丰富的查询语言,同时实现了可配置、可扩展,并对索引、搜索性能进行了优化。Solr是一个全文检索服务器,只需要进行配置就可以实现全文检索服务。有效降低频繁访问数据库对数据库造成的压力。第一步:将solr部署在linux系统下。第二步:solrJ是solr的客户端,使用它需要依赖solrJ的jar包。第三步:将数据库的内容添加到solr的索引库,这样查询就在索引库查询,而不是数据库了。controller层: - . .考试资料 - . - [AppleScript] 纯文本查看复制代码 ? Controller 01 RequestMapping(\ 02 public classItemController { 03 Autowired 04 private ItemService itemService; 05 RequestMapping(\ 06 ResponseBody 07 public TaotaoResult importAllItem(){ 08 TaotaoResult result=itemService.importAllItem(); 09 returnresult; 10 } 11 } [AppleScript] 纯文本查看复制代码 ? 01 package .taotao.search.mapper; 02 import java.util.List; 03 04 import .taotao.search.pojo.Item; 05 public interface ItemMapper { 06 - . .考试资料 - . - 07 List 10 11 mapper.xml [AppleScript] 纯文本查看复制代码 ? 01 02 04 12 b. NAME category_name 13 FROM 14 tb_item a - . .考试资料 - . - 15 LEFT JOIN tb_item_cat b ON a.cid =b.id 16 17 四步:从索引库查询的逻辑编写: [AppleScript] 纯文本查看复制代码 ? 01 //从索引库里面获取商品信息,现在这个dao层是从索引库获取信息,因为之02 前的写的逻辑是将db里面的数据导入到索引库。后面的查询都是从索引库中03 进行,而不从数据库了 04 Repository 05 public classSearchDaoImpl implements SearchDao { 06 Autowired 07 private SolrServer solrServer; 08 09 10 11 12 13 14 Override public SearchResult search(SolrQuery query)throws Exception { //这是从索引库里面,直接执行查询 QueryResponse response =solrServer.query(query); //获取查询的结果 SolrDocumentList documentList=response.getResults(); 15 SearchResult result=newSearchResult(); - . .考试资料 - . - 16 //这是获取总记录数 17 result.setRecordCount(documentList.getNumFound()); 18 List //商品的高亮显示,即当鼠标移到字上时,该字体变色,这20 是从QueryResponse中获取的 21 Map =response.getHighlighting(); 23 24 for(SolrDocument solrDocument :documentList){ 25 //每个SolrDocument都是一个商品pojo的内容,所26 以这里要创建一个商品的pojo对象,来获取详细的字段 27 Item item=newItem(); 28 item.setId((String)solrDocument.get(\ 29 //高亮显示是title的高亮显示 30 List )).get(\ 32 String title=\ 33 if(list!=null &&list.size()>0){ 34 title=list.get(0); 35 } 36 else{ 37 - . .考试资料 - . - 38 title=(String)solrDocument.get(\ 39 } 40 41 42 43 )); 44 45 item_category_name\ 46 47 _point\ 48 49 } 50 item.setTitle(title); item.setPrice((Long)solrDocument.get(\ item.setImage((String)solrDocument.get(\ item.setCategory_name((String)solrDocument.get(\ item.setSell_point((String)solrDocument.get(\ itemList.add(item); result.setItemList(itemList); returnresult; } } 第五步:索引库内容建立好后,开始编写对外的服务接口,即通过条件搜索具体的商品,比如手机,会显示出总共的手机列表信息,第几页,总共多少页,总共多少个搜索结果 - . .考试资料 - . - 请求的 url: file:///C:/Users/ADMINI~1.WIN/AppData/Local/Temp/V7(XMWRN]{G8~CI}BCCR3QC.gifarch/query?q={查询条件}&page={page}&rows={rows}返回的结果:TaotaoResult包装商品列表。创建一个sql语句对应的pojo,单独建立一个pojo用来装显示的内容列表: [AppleScript] 纯文本查看复制代码 ? 01 public classItem { 02 private String id; 03 private String title; 04 private String sell_point; 05 private long price; 06 private String image; 07 private String category_name; 08 private String item_des; 09 10} controller层: [AppleScript] 纯文本查看复制代码 ? 01 Controller 02 public classSearchController { 03 Autowired - . .考试资料 - . - 04 private SearchService searchService; 05 RequestMapping(value=\ 06 ResponseBody 07 public TaotaoResult search(RequestParam(\ 08 RequestParam(defaultValue=\ 09 RequestParam(defaultValue=\ 10 //查询条件不能为空 11 if(StringUtils.isBlank(queryString)){ 12 returnTaotaoResult.build(400,\查询条件不能为空\ 13 } 14 SearchResult searchResult =null; 15 try{ 16 queryString 17 =newString(queryString.getBytes(\ 18 searchResult 19 =searchService.search(queryString,page,rows); 20 }catch (Exception e){ 21 e.printStackTrace(); 22 returnTaotaoResult.build(500,ExceptionUtil.getStackTr23 ace(e)); 24 } 25 - . .考试资料 - . - 26 returnTaotaoResult.ok(searchResult); } } [AppleScript] 纯文本查看复制代码 ? 1 前提是要写好如何从索引库读取数据: 下面是服务的接口层编写:controller: [AppleScript] 纯文本查看复制代码 ? 01 Controller 02 public classSearchController { 03 Autowired 04 private SearchService searchService; 05 RequestMapping(value=\ 06 ResponseBody 07 public TaotaoResult search(RequestParam(\ 08 RequestParam(defaultValue=\ 09 RequestParam(defaultValue=\ 10 //查询条件不能为空 11 if(StringUtils.isBlank(queryString)){ 12 returnTaotaoResult.build(400,\查询条件不能为空\ 13 - . .考试资料 - . - 14 } 15 SearchResult searchResult =null; 16 try{ 17 queryString 18 =newString(queryString.getBytes(\ 19 searchResult 20 =searchService.search(queryString,page,rows); 21 }catch (Exception e){ 22 e.printStackTrace(); 23 returnTaotaoResult.build(500,ExceptionUtil.getStackTr24 ace(e)); 25 } 26 returnTaotaoResult.ok(searchResult); } } [AppleScript] 纯文本查看复制代码 ? Service 01 public classSearchServiceImpl implements SearchService { 02 Autowired 03 private SearchDao searchDao; 04 - . .考试资料 - . - 05 Override 06 public SearchResult search(String queryString,int page,int rows)throws 07 Exception { 08 SolrQuery query=newSolrQuery(); 09 query.setQuery(queryString); 10 query.setStart((page-1)*rows); 11 query.setRows(rows); 12 //设置默认的查询搜索域,即默认的查询 13 query.set(\ 14 //设置高亮显示 15 query.setHighlight(true); 16 17 query.addHighlightField(\ 18 query.setHighlightSimplePre(\19 query.setHighlightSimplePost(\ 20 //执行查询 21 SearchResult searchResult =searchDao.search(query); 22 //根据结果来计算商品总共多少页 23 long recordCount=searchResult.getRecordCount(); 24 long pageCount=recordCount/rows; 25 if(recordCount % rows >0){ 26 pageCount++; - . .考试资料 - . - 27 } 28 searchResult.setPageCount(pageCount); 29 searchResult.setCurPage((long)page); 30 31 32 33 } 34 35 客户端通过输入商品来实现搜索功能:controller层:Controller [AppleScript] 纯文本查看复制代码 returnsearchResult; } ? public classSearchController { 01 Autowired 02 private SearchService searchService; 03 04 RequestMapping(\ 05 public String search(RequestParam(\ 06 queryString,RequestParam(defaultValue=\ 07 if(queryString !=null){ 08 try{ 09 queryString 10 =newString(queryString.getBytes(\ - . .考试资料 - . - 11 }catch (UnsupportedEncodingException e){ 12 e.printStackTrace(); 13 } 14 } 15 SearchResult searchResult 16 =searchService.search(queryString,page); 17 //向页面传递参数 18 model.addAttribute(\ 19 //model.addAttribute(\ 20 model.addAttribute(\ 21 model.addAttribute(\ 22 return\ 23 24 } } service层: [AppleScript] 纯文本查看复制代码 ? Service 01 public classSearchServiceImpl implements SearchService { 02 03 Value(\ 04 private String SEARCH_BASE_URL; - . .考试资料 - . - 05 Override 06 public SearchResult search(String queryString,int page){ 07 //这里需要的是连接+参数.这里每页显示的记录条数,可以08 传递也可以不用传递 09 //调用taotao-search的服务 10 //查询参数 11 Map param.put(\ 13 param.put(\ 14 try{ 15 //调用服务 16 String json 17 =HttpClientUtil.doGet(SEARCH_BASE_URL,param); 18 //把字符串转换成java对象 19 TaotaoResult taotaoResult 20 =TaotaoResult.formatToPojo(json,SearchResult.class); 21 SearchResult 22 result=(SearchResult)taotaoResult.getData(); 23 returnresult; 24 /* if(taotaoResult.getStatus()==200){ 25 26 }*/ - . .考试资料 - . - 27 28 }catch (Exception e){ e.printStackTrace(); 29 returnnull; 30 } 31 32 } 33 } - . .考试资料
service层编写:
多表查询商品,显示在页面的逻辑编写:12
mapper.java