全文检索技术ElasticSearch

第1章  全文检索技术

1.1概述

现在企业开发中,更常用是的 solr 搜索服务器和 ElasticSearch 搜索服务器

是通过Resyful风格API简化客户端 对lunence的使用

1.1.1和数据库进行对比分析

索引:相当于DB 存储数据的逻辑位置

类型:相当于表 ·

文档:相当于行数据,通过词条搜索出来数据

文档的属性field:相当于表中的列

 

 

服务的默认端口是: 9300

控制页面的端口号是: 9200

1.2ElasticSearch 搜索服务器安装

官网: https://www.elastic.co/products/elasticsearch

包结构:

bin 存放 elasticSearch 运行命令

config 存放配置文件

lib 存放 elasticSearch 运行依赖 jar

modules 存放 elasticSearch 模块

plugins 存放插件

环境配置:

运行 elasticSearch/bin/elasticsearch.bat 文件

配置 JAVA_HOME 环境变量

访问 http://127.0.0.1:9200

1.3 ElasticSearch  插件安装 es head图形化界面

1.3.1在线下载安装

1.进入到bin目录

       2.执行plugin.bat install mobz/elasticsearch-head

       3.head插件安装到plugins目录下

      

1.3.2      如果在线安装失败

       1.head下载到本地

       2.head插件放置到plugins中即可

       访问:http://localhost:9200/_plugin/head/

看到下图表示安装成功:

1.4集成IK分词器

1.4.1下载开源包

  https://github.com/medcl/elasticsearch-analysis-ik/tree/2.x

1.4.2打包 ik 分词器

输入命令:mvn clean package

1.4.3进入 ik包中的target/release 目录

将下列文件,复制到EslasticSerarch文件夹的plugins/analysis-ik

1.4.4进入 IK目录下target/release/config 目录

将所有配置文件,复制到EslasticSerarch文件夹的config

1.4.5在配置 ES/config/elasticsearch.yml

在其最底下加入:

index.analysis.analyzer.ik.type:    "ik"

重启ES发现 ik 分词器被加载

1.4.6访问:

http://localhost:9200/_analyze?analyzer=ik&pretty=true&text=我是中国人

集成成功

1.5Spring data ElasticSearch的使用

1.5.1导入Maven依赖包:

<!-- elasticsearch  -->

<dependency>

    <groupId>org.elasticsearch</groupId>

    <artifactId>elasticsearch</artifactId>

    <version>2.4.0</version>

</dependency>

<dependency>

    <groupId>org.springframework.data</groupId>

    <artifactId>spring-data-elasticsearch</artifactId>

    <version>2.0.4.RELEASE</version>

</dependency>

 

1.5.2配置文件

applicationContext-elasticsearch.xml:

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

    xmlns:elasticsearch="http://www.springframework.org/schema/data/elasticsearch"

    xsi:schemaLocation="

       http://www.springframework.org/schema/beans

       http://www.springframework.org/schema/beans/spring-beans.xsd

       http://www.springframework.org/schema/data/elasticsearch

       http://www.springframework.org/schema/data/elasticsearch/spring-elasticsearch-1.0.xsd">

   

    <!-- 搜索DAO 扫描 -->

    <elasticsearch:repositories base-package="cn.peihua.bos.index" />

   

    <!-- 配置Client -->

    <elasticsearch:transport-client id="client" cluster-nodes="127.0.0.1:9300"/>

   

    <!-- 配置搜索模板-->

    <bean id="elasticsearchTemplate"

       class="org.springframework.data.elasticsearch.core.ElasticsearchTemplate">

       <constructor-arg name="client" ref="client"/>

    </bean>

</beans>

applicationContext.xml中引入:

<!-- 引入elasticSearch -->

<import resource="applicationContext-elasticsearch.xml"/>

 

1.5.3编写domain

说明:本次案例数据访问技术选用的是Hibernate注解方式
 

实体映射关系:

@Document 文档对象 (索引名、文档类型 )

@Id 文档主键 唯一标识

注意:

       实体类中不光需要导入jpa@id还需要@org.springframework.data.annotation.Id

id注解

@Field 每个文档的字段配置(类型、是否分词、是否存储、分词器

Field属性:说明

index = FieldIndex.not_analyzed 表示不分词

index = FieldIndex.analyzed   表示今次那个分词

store = true 表示进行ES存储

analyzer = "ik" 表示存储的分词器为ik

searchAnalyzer = "ik" 表示查询的分词器为ik

注意:

       除了id外其他数字类型的字段不能进行分词

 

package cn. peihua.bos.domain.take_delivery;

 

import java.io.Serializable;

 

import javax.persistence.Column;

import javax.persistence.Entity;

import javax.persistence.GeneratedValue;

import javax.persistence.Id;

import javax.persistence.JoinColumn;

import javax.persistence.OneToOne;

import javax.persistence.Table;

 

import org.springframework.data.elasticsearch.annotations.Document;

import org.springframework.data.elasticsearch.annotations.Field;

import org.springframework.data.elasticsearch.annotations.FieldIndex;

import org.springframework.data.elasticsearch.annotations.FieldType;

 

import cn.peihua.bos.domain.base.Area;

 

/**

 * @description:运单实体类

 */

@Entity

@Table(name = "T_WAY_BILL")

@Document(indexName = "bos", type = "waybill")

publicclass WayBillimplements Serializable {

 

    @Id

    @GeneratedValue

    @Column(name = "C_ID")

    @org.springframework.data.annotation.Id

    @Field(index = FieldIndex.not_analyzed, store = true, type = FieldType.Integer)

    private Integer id;

    @Column(name = "C_WAY_BILL_NUM", unique = true)

    @Field(index = FieldIndex.not_analyzed, store = true, type = FieldType.String)

    private String wayBillNum; // 运单编号

    @OneToOne

    @JoinColumn(name = "C_ORDER_ID")

    private Order order; // 订单信息

 

    @Column(name = "C_SEND_NAME")

    @Field(index = FieldIndex.analyzed, analyzer = "ik", searchAnalyzer = "ik", store = true, type = FieldType.String)

    private String sendName; // 寄件人姓名

    @Column(name = "C_SEND_MOBILE")

    @Field(index = FieldIndex.analyzed, analyzer = "ik", searchAnalyzer = "ik", store = true, type = FieldType.String)

    private String sendMobile;// 寄件人电话

    @Column(name = "C_SEND_COMPANY")

    @Field(index = FieldIndex.analyzed, analyzer = "ik", searchAnalyzer = "ik", store = true, type = FieldType.String)

    private String sendCompany;// 寄件人公司

 

  ……………………

 

 

1.5.4编写索引库dao

注意:这个索引的dao不要和原先的dao放在一个包下

 

package cn.peihua.bos.index;

 

import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;

 

import cn.peihua.bos.domain.take_delivery.WayBill;

 

publicinterface WayBillIndexRepository extends

       ElasticsearchRepository<WayBill, Integer> {

 

}

 

 

1.5.5编写service

service中注入WayBillIndexRepository

在保存进数据库的同时保存索引库

//注入索引dao

    @Autowired

    private WayBillIndexRepository wayBillIndexRepository;

在方法中直接进行调用:

wayBillRepository.save(wayBill);

 

1.6进行ElasticSearch查询

1.6.1查询方式

建议:

查询可以结合分词结果查看,有助于查询结果判断

http://localhost:9200/_analyze?analyzer=ik&pretty=true&text=我是中国人

TermQuery 不能带条件的词条等值查询

WildcardQuery 模糊查询

BooleanQuery 布尔查询:可以用来组合多个查询条件

       //must 条件必须成立 相当于 and

       //must not 条件必须不成立 相当于 not

       //should 条件可以成立 相当于or

QueryBuileders.queryStringQuery(内容) 分词查询方法 默认范围是全字段,也可以指定字段

       如果是默认分词器:就按单个字查询

       如果是ik分词器:就是 可以带条件 的分词等值查询

 

 

//有条件分页查询运单

    public Page<WayBill> findPageData(WayBill wayBill, Pageable pageable) {

       //判断是否是条件查询,即判断wayBill中,条件是否存在  

       if (StringUtils.isBlank(wayBill.getWayBillNum())

              && StringUtils.isBlank(wayBill.getSendAddress())

              && StringUtils.isBlank(wayBill.getRecAddress())

              && StringUtils.isBlank(wayBill.getSendProNum())

              && (wayBill.getSignStatus() == null || wayBill.getSignStatus() == 0)) {

           //无条件,直接分页查询数据库

           returnwayBillRepository.findAll(pageable);

       }else{

           //查询条件

           //must 条件必须成立相当于 and

           //must not 条件必须不成立相当于 not

           //should 条件可以成立相当于or

          

           //创建条件组合查询对象boolQuery

           BoolQueryBuilder query = new BoolQueryBuilder();

          

           //构建组合条件,并将其加入到组合对象中:

          

           //1.等值查询运单号

           if(StringUtils.isNoneBlank(wayBill.getWayBillNum())){

              //如果订单号不为空,就进行等值查询

             

              //创建无条件等值查询对象

              QueryBuilder termQuery = new TermQueryBuilder("wayBillNum",

                     wayBill.getWayBillNum());

              query.must(termQuery);

             

           }

           //2.查询发货地

           if(StringUtils.isNoneBlank(wayBill.getSendAddress())){

              //如果发货地址不为空,进行查询

             

              //情况一:用户输入的仅是次词条的一部分,使用模糊查询

             

              //创建模糊查询对象

              QueryBuilder wildcardQueryBuilder = new WildcardQueryBuilder(

                     "sendAddress", "*"+wayBill.getSendAddress()+"*");

             

              //情况二:用户输入北京市海淀区,是多个词条的组合,使用带条件的等值查询

              //.feild()指定查询字段

              QueryBuilder queryStringQueryBuilder = new

                     QueryStringQueryBuilder(wayBill.getSendAddress())

                     .field("sendAddress")

                     .defaultOperator(Operator.AND);

              //对两种情况取(should)or

              BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();

              boolQueryBuilder.should(wildcardQueryBuilder);

              boolQueryBuilder.should(queryStringQueryBuilder);

             

              //加入总条件查询对象中

              query.must(boolQueryBuilder);

             

           }

           //3.查询收货地

           if(StringUtils.isNoneBlank(wayBill.getRecAddress())){

              //如果发货地址不为空,进行查询

             

              //情况一:用户输入的仅是次词条的一部分,使用模糊查询

             

              //创建模糊查询对象

              QueryBuilder wildcardQueryBuilder = new WildcardQueryBuilder(

                     "recAddress", "*"+wayBill.getRecAddress()+"*");

             

              //情况二:用户输入北京市海淀区,是多个词条的组合,使用带条件的等值查询

              //.feild()指定查询字段

              QueryBuilder queryStringQueryBuilder = new

                     QueryStringQueryBuilder(wayBill.getRecAddress())

                     .field("recAddress")

                     .defaultOperator(Operator.AND);

              //对两种情况取(should)or

              BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();

              boolQueryBuilder.should(wildcardQueryBuilder);

              boolQueryBuilder.should(queryStringQueryBuilder);

             

              //加入总条件查询对象中

              query.must(boolQueryBuilder);

             

           }

           //4.等值查询产品类型编号

           if (StringUtils.isNoneBlank(wayBill.getSendProNum())) {

              // 速运类型等值查询

              QueryBuilder termQuery = new TermQueryBuilder("sendProNum",

                     wayBill.getSendProNum());

              query.must(termQuery);

           }

           //等值查询运单签收状态

           if(wayBill.getSignStatus() != null && wayBill.getSignStatus() != 0){

               //如果运单签收状态不为空,进行无条件的等值查询

              QueryBuilder TermQuery = new

                     TermQueryBuilder("signStatus", wayBill.getSignStatus());

             

              query.must(TermQuery);

           }

          

 

 

 

           SearchQuery searchQuery = new NativeSearchQuery(query);

           searchQuery.setPageable(pageable); // 分页效果

           // 有条件查询、查询索引库

           returnwayBillIndexRepository.search(searchQuery);

          

       }

    }

 

 



猜你喜欢

转载自www.cnblogs.com/toby-ruan/p/8919636.html