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

[经验分享] 利用solr实现商品的搜索功能

[复制链接]

尚未签到

发表于 2017-12-19 08:36:51 | 显示全部楼层 |阅读模式
  
  后期补充:
  为什么要用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; }}<br>service层编写:<br>多表查询商品,显示在页面的逻辑编写:<br>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>"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>
DSC0000.png

  第四步:从索引库查询的逻辑编写:
?//从索引库里面获取商品信息,现在这个dao层是从索引库获取信息,因为之前的写的逻辑是将db里面的数据导入到索引库。后面的查询都是从索引库中进行,而不从数据库了@Repositorypublic 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>"";            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;    } }  第五步:索引库内容建立好后,开始编写对外的服务接口,即通过条件搜索具体的商品,比如手机,会显示出总共的手机列表信息,第几页,总共多少页,总共多少个搜索结果
DSC0001.png

  请求的url:
  /search/query?q={查询条件}&page={page}&rows={rows}
  返回的结果:TaotaoResult包装商品列表。
  创建一个sql语句对应的pojo,单独建立一个pojo
  用来装显示的内容列表:
?public class Item {     private String>     private String>     private String sell_point;     private long price;     private String image;     private String category_name;     private String item_des; }  controller层:
?@Controllerpublic 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);             }       }<br><br><br>?<span style="font-size: 16px">service层:利用solrJ的solrQurery来查询:</span>  前提是要写好如何从索引库读取数据:  
  下面是服务的接口层编写:
  controller:
?@Controllerpublic 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);             }       }?@Servicepublic 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层:
?@Servicepublic 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;        }         } }

运维网声明 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-425587-1-1.html 上篇帖子: Solr.NET快速入门(二) 下篇帖子: solr 打分和排序机制(转载)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

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

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

扫描微信二维码查看详情

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


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


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


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



合作伙伴: 青云cloud

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