ElasticSearch

一款非常强大的开源搜索引擎, 具备非常多强大功能,可以帮助从海量数据中快速找到需要的信息
(主要是模糊查找(根据词条))
例如 : 电商平台搜索商品 百度搜索答案 打车软件搜索附近的车等

ELK技术栈

ELK: elasticsearch结合kibana、Logstash、Beats ,被广泛应用于日志数据分析、实时监控等领域。
elasticsearch是elastic stack的核心,负责存储、搜索、分析数据。

Lucene: Apaache的开源搜索引擎类库,提供了搜索引擎的核心API


正向索引和反向索引

正向索引:是最传统的,根据id索引的方式。但根据词条查询时,必须先逐条获取每个文档,然后判断文档中是否包含所需要的词条,是根据文档找词条的过程
倒排索引:与正向索引相反,是先找到用户要搜索的词条,根据词条得到保护词条的文档的id,然后根据id获取文档。是根据词条找文档的过程

二者的优缺点

正向索引

  • 优点:
    • 可以给多个字段创建索引
    • 根据索引字段搜索、排序速度非常快
  • 缺点:
    • 根据非索引字段,或者索引字段中的部分词条查找时,只能全表扫描。

倒排索引

  • 优点:
    • 根据词条搜索、模糊搜索时,速度非常快
  • 缺点:
    • 只能给词条创建索引,而不是字段
    • 无法根据字段做排序

mysql和es对比

image.png
Mysql:擅长事务类型操作,可以确保数据的安全和一致性
ElasticSearch:擅长海量数据的搜索、分析、计算

在企业中,往往是两者结合使用:

  • 对安全性要求较高的写操作,使用mysql实现
  • 对查询性能要求较高的搜索需求,使用elasticsearch实现
  • 两者再基于某种方式,实现数据的同步,保证一致性

索引库操作

索引库就类似数据库表,mapping映射就类似表的结构。
mapping属性映射:
mapping是对索引库中文档的约束,常见的mapping属性包括:

  • type:字段数据类型,常见的简单类型有:
    • 字符串:text(可分词的文本)、keyword(精确值,例如:品牌、国家、ip地址)
    • 数值:long、integer、short、byte、double、float、
    • 布尔:boolean
    • 日期:date
    • 对象:object
  • index:是否创建索引,默认为true
  • analyzer:使用哪种分词器
  • properties:该字段的子字段

索引库操作:?

  • 创建索引库:PUT /索引库名
  • 查询索引库:GET /索引库名
  • 删除索引库:DELETE /索引库名
  • 添加字段:PUT /索引库名/_mapping

文档操作

文档操作:

  • 创建文档:POST /{索引库名}/_doc/文档id { json文档 }
  • 查询文档:GET /{索引库名}/_doc/文档id
  • 删除文档:DELETE /{索引库名}/_doc/文档id
  • 修改文档:
    • 全量修改:PUT /{索引库名}/_doc/文档id { json文档 }
    • 增量修改:POST /{索引库名}/_update/文档id { “doc”: {字段}}

中文分词器

分词器的作用:
创建倒排索引时对文档分词
用户搜索时,对输入的内容分词

一般使用IK分词器 ,包含两种模式:
ik_smart: 智能切分,粗粒度
ik_max_word:最细切分,细粒度

IK分词器如何拓展词条 如何停用词条

利用config目录的IkAnalyzer.cfg.xml文件添加拓展词典和停用词典
image.png

在词典中添加拓展词条或者停用词条:
编辑在配置文件中绑定的文件,添加拓展词或停用词

Java中操作ES

1.操作索引库

引入es的RestHighLevelClient依赖:

  1. <dependency>
  2. <groupId>org.elasticsearch.client</groupId>
  3. <artifactId>elasticsearch-rest-high-level-client</artifactId>
  4. </dependency>
  5. //因为SpringBoot默认的ES版本是7.6.2,所以我们需要覆盖默认的ES版本:
  6. <properties>
  7. <java.version>1.8</java.version>
  8. <elasticsearch.version>7.12.1</elasticsearch.version>
  9. </properties>

初始化RestHighLevelClient(客户端):

public class HotelIndexTest {
    private RestHighLevelClient client;

//代码执行前初始化客户端
    @BeforeEach
    void setUp() {
        this.client = new RestHighLevelClient(RestClient.builder(
                HttpHost.create("http://192.168.19.99:9200")
        ));
    }

  //执行后关闭资源
    @AfterEach
    void tearDown() throws IOException {
        this.client.close();
    }
}

创建索引库
代码分为三步:

  • 1)创建Request对象。因为是创建索引库的操作,因此Request是CreateIndexRequest。
  • CreateIndexRequest request = new CreateIndexRequest(“hotel”);
  • 2)添加请求参数,其实就是DSL的JSON参数部分。因为json字符串很长,这里是定义了静态字符串常量MAPPING_TEMPLATE,让代码看起来更加优雅。
  • request.source(MAPPING_TEMPLATE, XContentType.JSON);
  • 3)发送请求,client.indices()方法的返回值是IndicesClient类型,封装了所有与索引库操作有关的方法。
  • client.indices().create(request, RequestOptions.DEFAULT);

操作索引索引库时客户端需要先调用indices()方法

JavaRestClient操作elasticsearch的流程基本类似。核心是client.indices()方法来获取索引库的操作对象。
索引库操作的基本步骤:

  • 初始化RestHighLevelClient
  • 创建XxxIndexRequest。XXX是Create(创建)、Get(查询)、Delete(删除)
  • 准备DSL( Create时需要,其它是无参)
  • 发送请求。调用RestHighLevelClient#indices().xxx()方法,xxx是create、exists、delete

2.操作文档

初始化RestHighLevelClient(客户端):

public class HotelIndexTest {
    private RestHighLevelClient client;

//代码执行前初始化客户端
    @BeforeEach
    void setUp() {
        this.client = new RestHighLevelClient(RestClient.builder(
                HttpHost.create("http://192.168.19.99:9200")
        ));
    }

  //执行后关闭资源
    @AfterEach
    void tearDown() throws IOException {
        this.client.close();
    }
}

新增文档

//从数据库查询出要新增的信息
// 1.根据id查询酒店数据
Hotel hotel = hotelService.getById(61083L);
// 2.转换为文档类型
HotelDoc hotelDoc = new HotelDoc(hotel);
// 3.将HotelDoc转json
String json = JSON.toJSONString(hotelDoc);

  • 1)创建Request对象
  • IndexRequest request = new IndexRequest(“hotel”).id(hotelDoc.getId().toString());
  • 2)准备请求参数,也就是DSL中的JSON文档
  • request.source(json, XContentType.JSON);
  • 3)发送请求
  • client.index(request, RequestOptions.DEFAULT);

操作文档时,客户端不需要调用indices()

文档操作的基本步骤:

  • 初始化RestHighLevelClient
  • 创建XxxRequest。XXX是Index、Get、Update、Delete、Bulk
  • 准备参数(Index、Update、Bulk时需要)
  • 发送请求。调用RestHighLevelClient#.xxx()方法,xxx是index(新增)、get(查询)、update(修改)、delete(删除)、bulk(批量增加)
  • 解析结果(Get时需要)