微服务架构Day37-Dubbo之全文搜索

2021-04-02  本文已影响0人  攻城狮Chova

Solr

Apache Solr特点

Solr是Lucene的Java API包装,使用Solr,就可以使用Lucene的所有功能

搜索引擎

搜索引擎组件

搜索引擎有三个组件:

搜索引擎工作流程

分词技术

中文分词算法

基于字符串匹配
基于统计及机器学习的分词方式

IKAnalyzer

部署Solr并安装IKAnalyzer

/usr/local/docker/solr              用于存放docker-compose.yml配置文件
/usr/local/docker/solr/ikanalyzer   用于存放Dockerfile镜像配置文件
version: '3.1'
services:
 solr:
  build: ikanalyzer
  restart: always
  container_name: solr
  ports:
   - 8983:8983
  volumes:
   - ./solrdata:/opt/solrdata
FROM solr

# 创建Core
WORKDIR /opt/solr/server/solr
RUN mkdir ik_core
WORKDIR /opt/solr/server/solr/ik_core
RUN echo 'name=ik_core' > core.properties
RUN mkdir data
RUN cp -r ../configsets/sample_techproducts_configs/conf/ .

# 安装中文分词
WORKDIR /opt/solr/server/solr-webapp/webapp/WEB-INF/lib
ADD ik-analyzer-solr5-5.x.jar .
ADD solr-analyzer-ik-5.1.0.jar .
WORKDIR /opt/solr/server/solr-webapp/webapp/WEB-INF
ADD ext.dic .
ADD stopword.dic .
ADD IKAnalyzer.cfg.xml .

# 增加分词配置
COPY managed-schema /opt/solr/server/solr/ik_core/conf

WORKDIR /opt/solr
docker-compose up -d

Solr分析功能

修改managed-schema配置业务系统字段

<!-- 字段域 -->
<field name="tb_item_cid" type="plong" indexed="true" stored="true" />
<field name="tb_item_cname" type="text_ik" indexed="true" stored="true" />
<field name="tb_item_title" type="text_ik" indexed="true" stored="true" />
<field name="tb_item_sell_point" type="text_ik" indexed="true" stored="true" />
<field name="tb_item_desc" type="text_ik" indexed="true" stored="true" />

<!-- 复制域:Solr的搜索优化功能,,将多个字段复制到一个域,提高查询效率 -->
<field name="tb_item_keywords" type="text_ik" indexed="true" stored="false" multiValued="true" />
<copyField source="tb_item_cname" dest="tb_item_keywords">
<copyField source="tb_item_title" dest="tb_item_keywords">
<copyField source="tb_item_sell_point" dest="tb_item_keywords">
<copyField source="tb_item_desc" dest="tb_item_keywords">

复制配置到容器

docker cp managed-schema solr:/opt/solr/server/solr/ik_core/conf

重启容器

docker-compose restart

SpringBoot整合Solr

创建搜索服务接口

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>com.funtl</groupId>
        <artifactId>myshop-dependencies</artifactId>
        <version>1.0.0-SNAPSHOT</version>
        <relativePath>../myshop-dependencies/pom.xml</relativePath>
    </parent>

    <artifactId>myshop-service-search-api</artifacteId>
    <packaging>jar<packaging>
</project>
package com.oxford.myshop.service.search.api;

public interface SearchService {
    List<TbItemResult> search(String query,int page,int rows);
}
package com.oxford.myshop.service.search.domain;

import java.io.Serializable;

public class TbItemResult implements Serializable {
    private long id;
    private long tbTtemCid;
    private String tbItemCname;
    private String tbItemTitle;
    private String tbItemSellPoint;
    private String tbItemDesc;

    public long getId(){
        return id;
    }

    public void setId(long id){
        this.id=id;
    }
    
    public long getTbTtemCid(){
        return tbTtemCid;
    }

    public void setTbTtemCid(long tbTtemCid){
        this.tbTtemCid=tbTtemCid;
    }

    public String getTbItemCname(){
        return tbItemCname;
    }

    public void setTbItemCname(String tbItemCname){
        this.tbItemCname=tbItemCname;
    }

    public String getTbItemTitle(){
        return tbItemTitle;
    }

    public void setTbItemTitle(String tbItemTitle){
        this.tbItemTitle=tbItemTitle;
    }

    public String getTbItemSellPoint(){
        return tbItemSellPoint;
    }

    public void setTbItemSellPoint(String tbItemSellPoint){
        this.tbItemSellPoint=tbItemSellPoint;
    }
    
    public String getTbItemDesc(){
        return tbItemDesc;
    }

    public void setTbItemDesc(String tbItemDesc){
        this.tbItemDesc=tbItemDesc;
    }
}

创建搜索服务提供者

package com.oxford.myshop.service.search.provider;

@EnableHystrix
@EnableHystrixDashboard
@SpringBootApplication(scanBasePackages="com.oxfrod.myshop")
@MapperScan(basePackages="com.oxford.myshop.service.search.provider.mapper")
public class MyShopServiceSearchProviderApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyShopServiceSearchProviderApplication.class,args);
        Main.main(args);
    }
}
package com.oxford.myshop.service.search.provider.mapper;

@Respository
public interface TbItemResultMapper {
    List<TbItemResult> selectAll();
}
Spring的四大注解:
1. @Controller
2. @Service
3. @Component
4. @Repository
<?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.oxford.myshop.service.search.provider.mapper.TbItemResultMapper">
  <resultMap id="BaseResultMap" type="com.oxford.myshop.service.search.domainTbItemResult">
    <id column="id" jdbcType="BIGINT" property="id" />
    <result column="tb_item_cid" jdbcType="BIGINT" property="tbItemCid" />
    <result column="tb_item_cname" jdbcType="VARCHAR" property="tbItemCname" />
    <result column="tb_item_title" jdbcType="VARCHAR" property="tbItemTitle" />
    <result column="tb_item_sell_point" jdbcType="VARCHAR" property="tbItemSellPoint" />
    <result column="tb_item_desc" jdbcType="VARCHAR" property="tbItemDesc" />
  </reslutMap>

  <select id="selectAll" resultMap="BaseResultMap">
    select
        a.id,
        a.title as tb_item_title,
        a.sell_point as tb_item_sell_point,
        a.cid as tb_item_cid,
        b.name as tb_item_cname,
        c.item_desc as tb_item_desc
    from
        tb_item as a
        left join tb_item_cat as b
            on a.cid=b.id
        left join tb_item_desc as c
            on a.id=c.item_id
  </select>
</mapper>
初始化Solr:

public void initSolr() {
    List<TbItemResult> tbItemResult=tbItemResultMapper.selectAll();

    try{
        SolrInputDocument document=null;
        for(TbItemResult tbItemResult:tbItemResults){
            document=new SolrInputDocument();
            document.addFiled("id",tbItemResult.getId());
            document.addFiled("tb_item_cid",tbItemResult.getTbItemCid());
            document.addFiled("tb_item_cname",tbItemResult.getTbItemCname());
            document.addFiled("tb_item_title",tbItemResult.getTbItemTitle());
            document.addFiled("tb_item_sell_point",tbItemResult.getTbItemSellPoint());
            document.addFiled("tb_item_desc",tbItemResult.getTbItemDesc());
        
            solrClient.add(document);
            solrClient.commit();
        }
    }catch(SolrServerException e){
        e.printStackTrace();
    }catch(IOException e){
        e.printStackTrace();
    }   
}
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
搜索Solr:

public void searchSolr(){
    SolrQuery query=new SolrQuery();
    // 设置查询条件
    query.setQuery("手机");
    // 分页查询
    query.setStart(0);
    query.setRows(10);
    // 设置查询的默认域
    query.set("df","tb_item_keywords");
    // 设置高亮显示
    query.setHighlight(true);
    query.addHighlightField("tb_item_title");
    query.setHighlightSimplePre("<span style='color:red;'>");
    query.setHighlightSimplePost("</span>");

    // 开始查询
    try{
        QueryResponse queryResponse=solrClient.query(query);
        SolrDocumentList results=queryResponse.getResults();
        // 获取高亮
        Map<String,Map<String,List<String>>> highlighting=queryResponse.getHighlighting();
        for(SolrDocument result:results){
            List<String> strings=highlighting.get(result.get("id")).get(result.get("tb_item_title"))
            if(strings!=null&&strings.size()>0){
            String title=strings.get(0);
            System.out.println(title);
            }
        }
    }catch(SolrServerException e){
        e.printStackTrace();
    }catch(IOException e){
        e.printStackTrace();
    }
}
package com.oxford.myshop.service.search.provider.api.impl;

@Service(version="${services.versions.search.v1}")
public class SearchServiceImpl implements SearchService{

    @Autowired
    private SolrClient solrClient;
    
    @Override
    public List<TbItemResult> search(String query,int page,int rows){
        List<TbItemResult> searchResults=Lists.newArrayList();
        SolrQuery query=new SolrQuery();
        // 设置查询条件
        query.setQuery("手机");
        // 分页查询
        query.setStart((page-1)*rows);
        query.setRows(rows);
        // 设置查询的默认域
        query.set("df","tb_item_keywords");
        // 设置高亮显示
        query.setHighlight(true);
        query.addHighlightField("tb_item_title");
        query.setHighlightSimplePre("<span style='color:red;'>");
        query.setHighlightSimplePost("</span>");

    // 开始查询
    try{
        QueryResponse queryResponse=solrClient.query(query);
        SolrDocumentList results=queryResponse.getResults();
        // 获取高亮
        Map<String,Map<String,List<String>>> highlighting=queryResponse.getHighlighting();
        for(SolrDocument solrDocument:solrDocuments){
            TbItemResult result=new TbResult();
            result.setId(Long.parseLong(String.valueOf(solrDocument.get("id"))));
            result.setTbItemCid(Long.parseLong(String.valueOf(solrDocument.get("tb_item_cid"))));
            result.setTbItemCname((String)solrDocument.get("tb_item_cname"));
            result.setTbItemTitle((String)solrDocument.get("tb_item_title"));
            result.setTbItemSellPoint((String)solrDocument.get("tb_item_sell_point"));
            result.setTbItemDesc((String)solrDocument.get("tb_item_desc"));

            String tbItemTitle="";
            List<String> list=highlighting.get(result.get("id")).get(result.get("tb_item_title"))
            if(list!=null&&lsit.size()>0){
                String title=list.get(0);
            }else{
                tbItemTitle=(String)solrDocument.get("tb_item_title");
            }
            result.setTbItemTitle(tbItemTitle);
            searchResults.add(result);
        }
    }catch(SolrServerException e){
        e.printStackTrace();
    }catch(IOException e){
        e.printStackTrace();
    }
        return searchResults;
    }
}

创建搜索服务消费者

package com.oxford.myshop.service.search.consumer;

@EnableHystrix
@EnableHystrixDashboard
@SpringBootApplication(scanBasePackages="com.oxford.myshop",exclude=DataSourceAutoConfiguration.class)
public class MyShopServiceSearchConsumerApplication{
    public static void main(String[] args){
        SpringApplication.run(MyShopServiceSearchConsumerApplication.class,args);
        Main.main(args);
    }
}
package com.oxford.myshop.service.search.consumer.controller;

@RestController
public class SearchController{
    @Reference(version="${services.versions.search.v1}")
    private SearchService searchService;

    @RequestMapping(value="search/{query}/{page}/{rows}",method=RequestMethod.GET)
    public List<TbItemResult> search(
        @PathVariable(required=true) String query,
        @PathVariable(required=true) int page,
        @PathVariable(required=true) int rows
    ){
        return searchService.search(query,page,rows)
    }
}
上一篇下一篇

猜你喜欢

热点阅读