利用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;
 }
}<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 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);

 }
 }<br><br><br>
1
<span style="font-size: 16px">service层:利用solrJ的solrQurery来查询:</span>

前提是要写好如何从索引库读取数据:  

下面是服务的接口层编写:

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实现商品的搜索功能(实例讲解)就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • solr在java中的使用实例代码

    SolrJ是操作Solr的Java客户端,它提供了增加.修改.删除.查询Solr索引的JAVA接口.SolrJ针对 Solr提供了Rest 的HTTP接口进行了封装, SolrJ底层是通过使用httpClient中的方法来完成Solr的操作. jar包的引用(maven pom.xml): <dependency> <groupId>org.apache.solr</groupId> <artifactId>solr-solrj</artifactId

  • 利用solr实现商品的搜索功能(实例讲解)

    后期补充: 为什么要用solr服务,为什么要用luncence? 问题提出:当我们访问购物网站的时候,我们可以根据我们随意所想的内容输入关键字就可以查询出相关的内容,这是怎么做到呢?这些随意的数据不可能是根据数据库的字段查询的,那是怎么查询出来的呢,为什么千奇百怪的关键字都可以查询出来呢? 答案就是全文检索工具的实现,luncence采用了词元匹配和切分词.举个例子:北京天安门------luncence切分词:北京 京天 天安 安门 等等这些分词.所以我们搜索的时候都可以检索到. 有一种分词器

  • php利用scws实现mysql全文搜索功能的方法

    本文实例讲述了php利用scws实现mysql全文搜索功能的方法.分享给大家供大家参考.具体方法如下: scws这样的中文分词插件比较不错,简单的学习了一下,它包涵一些专有名称.人名.地名.数字年代等规则集合,可以直接将语句按这些规则分开成一个一个关键词,准确率在90%-95%之间,按照安装说明把scws的扩展放入php的扩展目录里,下载规则文件和词典文件,并在php配置文件中引用它们,就可以用scws进行分词了. 1) 修改 php 扩展代码以兼容支持 php 5.4.x 2) 修正 php

  • Android 百度地图POI搜索功能实例代码

    在没介绍正文之前先给大家说下poi是什么意思. 由于工作的关系,经常在文件中会看到POI这三个字母的缩写,但是一直对POI的概念和含义没有很详细的去研究其背后代表的意思.今天下班之前,又看到了POI这三个字母,决定认认真真的搜索一些POI具体的含义. POI是英文的缩写,原来的单词是point of interest, 直译成中文就是兴趣点的意思.兴趣点这个词最早来自于导航地图厂商.地图厂商为了提供尽可能多的位置信息,花费了很大的精力去寻找诸如加油站,餐馆,酒店,景点等目的地,这些目的地其实都可

  • Python 实现简单的shell sed替换功能(实例讲解)

    code: f = open('yesterday','r',encoding='utf-8') f2 = open('yesterday.bak','w',encoding='utf-8') old_str = input('请输入要修改的字符:') replace_str = input('请输入替换成的字符:') for line in f.readlines(): line = line.replace(old_str,replace_str) print(line) f2.write(

  • jQuery插件ImgAreaSelect实现头像上传预览和裁剪功能实例讲解一

    上一节随笔中,我们已经知道了关于jQuery插件ImgAreaSelect基本的知识:那么现在看一下实例: 首先,要知道我们应该实现什么功能? (1)图片能够实现上传预览功能 (2)拖拽裁剪图片,使其能够显示裁剪后的区域 (3)显示要裁剪区域的坐标 其次,该如何引用该插件呢? 那就具体看一下吧! 第一步:先将样式和文件包引入(根据你自己的位置引入) <!--引入imgareaselect的css样式--> <link rel="stylesheet" type=&qu

  • js + css实现标签内容切换功能(实例讲解)

    先附上效果图和代码: html 文档: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script type="text/javascript" src="../js/tabs_function.js"></scri

  • Asp.Mvc 2.0实现用户登录与注销功能实例讲解(2)

    这一节讲解下ASP.MVC 2.0的用户登录与注销功能,先讲登录,后说注销.我们这个系列讲的用户登录方式都是FORM表单验证方式.在讲之前先给大家说下<%:%>的功能,<%:%>与<%=%>功能一样,用来动态输出内容. 一.登录 1. 建立MODEL 登录的时候,我们一般只要验证用户名和密码,还有是否保存登录COOKIE,所以我们建立一个MODEL登录类,只需包括3个字段就可以. /// <summary> /// 用户登录MODEL /// </su

  • ThinkPHP实现ajax仿官网搜索功能实例

    本文实例讲述了ThinkPHP实现ajax仿官网搜索功能的方法.分享给大家供大家参考. 具体实现方法如下: 后台代码: 复制代码 代码如下: //搜索,如果在1不在0  function search(){      $keyword = $_POST['search'];      $Goods=M('goods');    //这里我做的一个模糊查询到名字或者对应的id,主要目的因为我这个系统是    //商城系统里面用到直接看产品ID      $map['goods_id|goods_n

  • mysql正则表达式(regexp和rlike)的搜索功能实例分析

    本文实例讲述了mysql正则表达式(regexp和rlike)的搜索功能.分享给大家供大家参考,具体如下: 我们知道正则表达式是描述搜索模式的特殊字符串. 它是一个强大的工具,为我们提供一种简洁灵活的方法来识别基于模式的文本字符,例如字符,单词等.例如,我们可以使用正则表达式来搜索电子邮件,IP地址,电话号码,社会安全号码或具有特定模式的任何内容.正则表达式可以由正则表达式处理器解释的自己的语法,正则表达式广泛应用于从编程语言到数据库(包括MySQL)大部分平台.使用正则表达式的优点是,不限于在

  • vue中的搜索关键字实例讲解

    目录 vue的搜索关键字 1.定义一个搜索框 2.循环遍历,之前 3.在data中,我们写入如下数据 4.在methods中 5.我们还可以这样写 搜索功能及搜索结果关键字高亮 首先实现搜索功能 通过computed计算属性监听搜索内容的变化 下边实现搜索关键字高亮显示 vue的搜索关键字 1.定义一个搜索框 <label>     搜索关键字:     <input type="search" name="" id="" va

随机推荐