基于solr7的搜索工程——淘淘商城(二十)

简介

  • taotao-search工程独立于rest,portal,manager工程,通过 http调用 solr服务器提供的索引服务完成对商品的检索。
  • 系统架构。
    8.taotaosearch.png

搭建

    <!-- solr客户端 -->
    <dependency>
      <groupId>org.apache.solr</groupId>
      <artifactId>solr-solrj</artifactId>
    </dependency>
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
    </dependency>
  • 在pom.xml中配置tomcat端口号为8083。
  • 在pom.xml中配置资源路径,将mapper包下的mapper的配置文件导出。
    • 默认路径为 src/main/resources ,配置之后的值覆盖默认值。pom的属性详解
    <!--资源映射-->
    <!--resources资源映射默认为/src/main/resources,如果配置会覆盖默认路径-->
    <resources>
      <resource>
        <directory>src/main/java</directory>
        <includes>
          <include>**/*.properties</include>
          <include>**/*.xml</include>
        </includes>
        <filtering>false</filtering>
      </resource>
      <resource>
        <directory>src/main/resources</directory>
        <includes>
          <include>**/*.properties</include>
          <include>**/*.xml</include>
        </includes>
        <filtering>false</filtering>
      </resource>
    </resources>
  • web.xml都改为search相关名称,url前缀为/search/。
  • mybatis-config.xml开启驼峰命名转换,用于数据库带 _ 的列名和java变量的驼峰命名转换,注意节点配置的顺序。mybatis核心配置文件的节点说明
<configuration>
  <settings>
    <!--驼峰命名转换-->
    <setting name="mapUnderscoreToCamelCase" value="true"/>
  </settings>

  <!--配置分页插件 -->
  <plugins>
    <plugin interceptor="com.github.pagehelper.PageInterceptor">
      <!-- property属性可以不用配置,新版本能自动识别底层数据库 -->
      <property name="helperDialect" value="mysql"/>
    </plugin>
  </plugins>

</configuration>
  • solr.properties和spirng-solr.xml配置solr服务器相关属性。
    • 注意solr7和solr4的配置有很大不同,现在的类名为HttpSolrClient,参考:solr7和solr4的区别
#solrcore的远程地址
SOLR.SERVER.URL=http://192.168.57.139:8983/solr/hjg
  <!-- 加载配置文件 -->
  <context:property-placeholder location="classpath:resource/*.properties"/>

  <!-- 配置SolrServer对象 -->
  <!-- 单机版 -->
  <bean id="solrClient" class="org.apache.solr.client.solrj.impl.HttpSolrClient">
    <constructor-arg name="builder" value="${SOLR.SERVER.URL}"/>
  </bean>

导入商品数据

需求

  • 导入所有商品信息,包括:id、标题、卖点、价格、图片、类目名称、商品描述。
  • 请求url:/search/manager/importall
  • 请求参数:无
  • 响应参数:TaoTaoResult,包含商品信息列表。

Dao层

  • 商品信息涉及三张表,tb_item,tb_item_cat,tb_item_desc。
  • 在pojo包下创建Item,储存商品信息。
public class Item {
    private String id;
    private String title;
    private String sellPoint;
    private long price;
    private String image;
    private String categoryName;
    private String itemDesc;
}
  • 在item下创建ItemMapper接口和映射文件,联结查询商品信息列表。
public interface ItemMapper {
    List<Item> getItemList();
}
?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,
    c.item_desc
    FROM
    tb_item a
    LEFT JOIN tb_item_cat b ON a.cid = b.id
    LEFT JOIN tb_item_desc c ON a.id = c.item_id

  </select>

</mapper>

Service层

  • 创建ItemService和实现类,从mysql中查询商品信息,并使用solrj将商品按照设置好的域名导入solr服务器的索引库,返回TaoTaoResult。
@Service
public class ItemServiceImpl implements ItemService {

    @Autowired
    private ItemMapper itemMapper;

    @Autowired
    private SolrClient solrClient;

    @Override
    public TaotaoResult importAllItems() {
        //从mysql中查询商品
        List<Item> itemList = itemMapper.getItemList();

        try {
            //将商品写入solr的索引
            for (Item item : itemList) {
                SolrInputDocument document = new SolrInputDocument();

                document.setField("id", item.getId());
                document.setField("item_title", item.getTitle());
                document.setField("item_sell_point", item.getSellPoint());
                document.setField("item_price", item.getPrice());
                document.setField("item_image", item.getImage());
                document.setField("item_category_name", item.getCategoryName());
                document.setField("item_desc", item.getItemDesc());

                solrClient.add(document);
            }
            //提交修改
            solrClient.commit();
        } catch (Exception e) {
            e.printStackTrace();
            return TaotaoResult.build(500, ExceptionUtil.getStackTrace(e));
        }

        return TaotaoResult.ok();
    }
}

Controller层

  • 创建ItemController,调用service层,将商品信息导入solr索引库,返回TaotaoResult。
@Controller
@RequestMapping("/manager")
public class ItemController {

    @Autowired
    private ItemService itemService;

    @RequestMapping("/importall")
    @ResponseBody
    public TaotaoResult importAllItems() {
        TaotaoResult result = itemService.importAllItems();
        return result;
    }

}

发布搜索服务

需求

  • 提供对外接口,根据查询字符串和分页查询信息,查询商品列表。
  • 请求url:/search/query?q={查询字符串}&page={page}&rows={rows}
  • 请求参数:查询字符串、分页信息page(默认1)和rows(默认60)。
  • 响应参数:TaoTaoResult,包装商品搜索结果。

Dao层

  • 根据SolrQuery查询,返回查询结果。
  • 在pojo下创建SearchResult,包含查询结果,总记录数,总页数,当前页。
public class SearchResult {
    //查询结果列表
    private List<?> list;
    //总记录数
    private long recordCount;
    //总页数
    private long pageCount;
    //当前页
    private long curPage;
}
  • 在dao下创建SearchDao和实现类,根据SolrQuery查询,将结果转换为Item列表,返回SearchResult。
    • 如果商品标题可设为高亮则设为高亮。
@Repository
public class SearchDaoImpl implements SearchDao {

    @Autowired
    private SolrClient solrClient;

    @Override
    public SearchResult search(SolrQuery query) throws Exception {
        SearchResult result = new SearchResult();

        QueryResponse queryResponse = solrClient.query(query);
        //获取查询结果
        SolrDocumentList solrDocuments = queryResponse.getResults();
        //获取高亮显示
        Map<String, Map<String, List<String>>> highlighting = queryResponse.getHighlighting();

        //发现的条数
        result.setRecordCount(solrDocuments.getNumFound());

        List<Item> itemList = new ArrayList<>();
        for (SolrDocument solrDocument : solrDocuments) {
            Item item = new Item();

            item.setId((String) solrDocument.get("id"));

            //高亮显示标题
            List<String> highlightList = highlighting.get(solrDocument.get("id")).get("item_title");
            String title = "";
            if (highlightList != null && highlightList.size() > 0) {
                title = highlightList.get(0);
            } else {
                title = (String) solrDocument.get("item_title");
            }
            item.setTitle(title);

            item.setImage((String) solrDocument.get("item_image"));
            item.setPrice((long) solrDocument.get("item_price"));
            item.setSellPoint((String) solrDocument.get("item_sell_point"));
            item.setCategoryName((String) solrDocument.get("item_category_name"));


            itemList.add(item);
        }

        result.setList(itemList);
        return result;

    }
}

Service层

  • 在service包下创建SearchService和实现类,根据查询字符串、分页信息设置SolrQuery,并设置默认搜索域、高亮文本前后缀,执行查询之后计算总页数,返回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(page);

        return searchResult;

    }
}

Controller层

  • controller包下创建SearchController,根据查询字符串、分页信息查询,返回包装查询结果的TaoTaoResult的json。
@Controller
@RequestMapping
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 {
            searchResult = searchService.search(queryString, page, rows);
        } catch (Exception e) {
            e.printStackTrace();
            return TaotaoResult.build(500, ExceptionUtil.getStackTrace(e));
        }
        return TaotaoResult.ok(searchResult);

    }
}

运行工程

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值