0


分布式搜索引擎ElasticSearch-1

1、初识ES

1.1.了解ES

1.1.1.作用

开源搜索引擎,从海量数据中快速找到需要的内容

1.1.2.ELK技术栈

elasticsearch结合kibana、Logstash、Beats,也就是elastic stack(ELK)。被广泛应用在日志数据分析、实时监控等领域。而elasticsearch是elastic stack的核心,负责存储、搜索、分析数据。
请添加图片描述

1.1.3.elasticsearch和Lucene

elasticsearch底层是基于lucene来实现的。

Lucene是一个Java语言的搜索引擎类库,提供了搜索引擎的核心API

Lucene优势:以扩展、高性能(基于倒排索引)
Lucene缺点:只限于Java语言开发、学习曲线陡峭、不支持水平扩展

1.2.倒排索引

倒排索引的概念是基于MySQL这样的正向索引。

1.2.1.正向索引

根据id建立索引。id和title建表,如果基于title做模糊查询,那么只能根据id进行逐行扫描。

是根据文档找词条的过程。

优点:

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

1.2.2.倒排索引

有两个非常重要的概念:

  • 文档(Document):用来搜索的数据,其中的每一条数据就是一个文档。
  • 词条(Term):对文档数据或用户搜索数据,利用某种算法分词,得到的具体含义的词语就是词条。分词。

创建倒排索引是对正向索引的一种特殊处理:

  • 将每一个文档的数据利用算法分词,得到一个个词条
  • 创建表,每行数据包括词条、词条所在文档id、位置等信息
  • 因为词条唯一性,可以给词条创建索引。

是根据词条找文档的过程。

优点:

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

1.3.ES的一些概念

文档

es是面向文档存储的,可以是数据库的一条商品数据、一个订单信息。文档数据会被序列化为json格式后存储在es中。

字段

json文档中往往包含很多的字段(field),类似于数据库中的列。

索引

相同类型的文档的集合,可以把索引当做数据库中的表。

映射

数据库的表会有约束信息,用来定义表的结构、字段的名称、类型等信息。因此索引库中的映射,就是索引中文档的字段约束信息,类似表的结构约束。

mysql

擅长事务类型操作,可以确保数据的安全和一致性

elasticsearch

擅长海量数据的搜索、分析、计算
MySQLElasticsearch说明TableIndex索引(index),就是文档的集合,类似数据库的表(table)RowDocument文档(Document),就是一条条的数据,类似数据库中的行(Row),文档都是JSON格式ColumnField字段(Field),就是JSON文档中的字段,类似数据库中的列(Column)SchemaMappingMapping(映射)是索引中文档的约束,例如字段类型约束。类似数据库的表结构(Schema)SQLDSLDSL是elasticsearch提供的JSON风格的请求语句,用来操作elasticsearch,实现CRUD

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

1.4.分词器

作用
  • 创建倒排索引时对文档分词
  • 用户搜索时,对输入的内容分词模式
  • ik_smart:只能切分,粗粒度
  • ik_max_work:最细切分,细粒度如何扩展词条、停用词条
  • 利用config牡蛎的IkAnalyzer.cfg.xml文件添加拓展词典和停用词典
  • 在词典中添加拓展词条或者停用词条 在ext.dic文件里添加拓展词条,在stopword.dic文件里添加停用词条。
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPEpropertiesSYSTEM"http://java.sun.com/dtd/properties.dtd"><properties><comment>IK Analyzer 扩展配置</comment><!--用户可以在这里配置自己的扩展字典--><entrykey="ext_dict">ext.dic</entry><!--用户可以在这里配置自己的扩展停止词字典  *** 添加停用词词典--><entrykey="ext_stopwords">stopword.dic</entry></properties>

2、索引库操作

Rest(PUT、GET、DELETE)

2.1.mapping映射属性

mapping是对索引库中文档的约束,常见的mapping属性包括:

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

2.2.索引库的CRUD

2.2.1.创建索引库

# PUT /索引库名称
PUT /heima
{"mappings": {"properties": {"info":{"type": "text","analyzer": "ik_smart"},"email":{"type": "keyword","index": "falsae"},"name":{"properties": {"firstName": {"type": "keyword"}}},//... 略
    }}}

2.2.2.修改索引库(添加字段)

索引库一旦创建,无法修改mapping中已有的字段,但是允许添加新字段到mapping中。

PUT /索引库名/_mapping
{"properties": {"新字段名":{"type": "integer"}}}

2.2.3.查看索引库

GET /索引库名

2.2.4.删除索引库

DELETE /索引库名

3、文档操作

3.1.新增文档

可以用post和put,但是post新增不指定id系统会自动新建一个id;而get不指定id系统不会分配。

POST /索引库名/_doc/文档id
{"字段1": "值1","字段2": "值2","字段3": {"子属性1": "值3","子属性2": "值4"},//...}

3.2.查询文档

GET /{索引库名称}/_doc/{id}

3.3.删除文档

DELETE /{索引库名}/_doc/id值

3.4.修改文档

  • 全量修改(id存在,即为修改;不存在,即为新增) 会删除旧文档,添加新文档
POST /索引库名/_doc/文档id
{"字段1": "值1","字段2": "值2","字段3": {"子属性1": "值3","子属性2": "值4"},//...}
  • 增量修改 修改指定字段的值
POST /{索引库名}/_update/文档id
{"doc": {"字段名": "新的值",}}

4、RestAPI

ES中支持两种地理坐标数据类型:

  • geo_point:点
  • geo_shape:多个点连接形成的形状

copy_to:将当前字段拷贝到指定字段

核心是client.indices()方法来获取索引库的操作对象。

4.1.初始化RestClient

在elasticsearch提供的API中,与elasticsearch一切交互都封装在一个名为RestHighLevelClient的类中,必须先完成这个对象的初始化,建立与elasticsearch的连接:
1、导入es的RestHighLevelClient依赖:

<dependency><groupId>org.elasticsearch.client</groupId><artifactId>elasticsearch-rest-high-level-client</artifactId></dependency>

2、因为SpringBoot默认的ES版本是7.6.2,所以我们需要覆盖默认的ES版本:

<properties><java.version>1.8</java.version><elasticsearch.version>7.12.1</elasticsearch.version></properties>

3、初始化RestHighLevelClient

RestHighLevelClient client =newRestHighLevelClient(RestClient.builder(//填写自己的IP值和端口HttpHost.create("http://192.168.150.101:9200")));

4.2.创建索引库

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

4.3.删除索引库

  • 1)创建Request对象。这次是DeleteIndexRequest对象
  • 2)准备参数。这里是无参
  • 3)发送请求。改用delete方法
@TestvoidtestDeleteHotelIndex()throwsIOException{// 1.创建Request对象DeleteIndexRequest request =newDeleteIndexRequest("hotel");// 2.发送请求
    client.indices().delete(request,RequestOptions.DEFAULT);}

4.4.判断索引库是否存在

  • 1)创建Request对象。这次是GetIndexRequest对象
  • 2)准备参数。这里是无参
  • 3)发送请求。改用exists方法
@TestvoidtestExistsHotelIndex()throwsIOException{// 1.创建Request对象GetIndexRequest request =newGetIndexRequest("hotel");// 2.发送请求boolean exists = client.indices().exists(request,RequestOptions.DEFAULT);// 3.输出System.err.println(exists ?"索引库已经存在!":"索引库不存在!");}

5、RestClient操作文档

数据库结构和索引库结构会不一致,所以需要新建类库来使结构保持一致。

5.1.新增文档

@TestvoidtestAddDocument()throwsIOException{// 1.根据id查询酒店数据Hotel hotel = hotelService.getById(61083L);// 2.转换为文档类型HotelDoc hotelDoc =newHotelDoc(hotel);// 3.将HotelDoc转jsonString json = JSON.toJSONString(hotelDoc);// 1.准备Request对象IndexRequest request =newIndexRequest("hotel").id(hotelDoc.getId().toString());// 2.准备Json文档
    request.source(json,XContentType.JSON);// 3.发送请求
    client.index(request,RequestOptions.DEFAULT);}

5.2.查询文档

@TestvoidtestGetDocumentById()throwsIOException{// 1.准备RequestGetRequest request =newGetRequest("hotel","61082");// 2.发送请求,得到响应GetResponse response = client.get(request,RequestOptions.DEFAULT);// 3.解析响应结果String json = response.getSourceAsString();HotelDoc hotelDoc = JSON.parseObject(json,HotelDoc.class);System.out.println(hotelDoc);}

5.3.删除文档

@TestvoidtestDeleteDocument()throwsIOException{// 1.准备RequestDeleteRequest request =newDeleteRequest("hotel","61083");// 2.发送请求
    client.delete(request,RequestOptions.DEFAULT);}

5.4.修改文档

  • 全量修改:与新增的API完全一致,如果新增时id已存在,则修改;如果新增时id不存在,则新增。
  • 增量修改:
@TestvoidtestUpdateDocument()throwsIOException{// 1.准备RequestUpdateRequest request =newUpdateRequest("hotel","61083");// 2.准备请求参数
    request.doc("price","952","starName","四钻");// 3.发送请求
    client.update(request,RequestOptions.DEFAULT);}

5.5.批量导入文档

BulkRequest做批量操作,有批量的增、删、查操作。

@TestvoidtestBulkRequest()throwsIOException{// 批量查询酒店数据List<Hotel> hotels = hotelService.list();// 1.创建RequestBulkRequest request =newBulkRequest();// 2.准备参数,添加多个新增的Requestfor(Hotel hotel : hotels){// 2.1.转换为文档类型HotelDocHotelDoc hotelDoc =newHotelDoc(hotel);// 2.2.创建新增文档的Request对象
        request.add(newIndexRequest("hotel").id(hotelDoc.getId().toString()).source(JSON.toJSONString(hotelDoc),XContentType.JSON));}// 3.发送请求
    client.bulk(request,RequestOptions.DEFAULT);}

本文转载自: https://blog.csdn.net/DOVISSSS/article/details/126776851
版权归原作者 endorphinnnn 所有, 如有侵权,请联系我们删除。

“分布式搜索引擎ElasticSearch-1”的评论:

还没有评论