Elasticsearch

Elasticsearch---高性能分布式搜索引擎

1、初识Elasticsearch

1.1、认识和安装

Elasticsearch结合kibana、logstash、Beats,是一整套技术栈,被叫做ELK。被广泛应用在日志数据分析、实时监控等领域

1.1.1、安装elasticsearch

通过下面的Docker命令安装单机版本的elasticsearch

Bash 复制代码
docker run -d \
  --name es \
  -e "ES_JAVA_OPTS=-Xms512m -Xmx512m" \
  -e "discovery.type=single-node" \
  -v es-data:/usr/share/elasticsearch/data \
  -v es-plugins:/usr/share/elasticsearch/plugins \
  --privileged \
  --network hm-net \
  -p 9200:9200 \
  -p 9300:9300 \
  elasticsearch:7.12.1
1.1.2、安装Kibana
Bash 复制代码
docker run -d \
--name kibana \
-e ELASTICSEARCH_HOSTS=http://es:9200 \
--network=hm-net \
-p 5601:5601  \
kibana:7.12.1

安装完成后,直接访问5601端口,即可看到控制台页面

选择Explore进入主页面:

然后选中Dev tools,进入开发工具页面:

1.2、倒排索引

传统数据库(如MySql)采用正向索引,例如下表中id创建索引:

elasticsearch采用倒排索引:

  • 文档(document):每条数据就是一个文档
  • 词条(term):文档按照语义分成的词语

1.3、IK分词器

中文分词往往需要根据语义分析,比较复杂,这就需要用到中文分词器,例如IK分词器。IK分词器是林良益在2006年开源发布的,其采用的正向迭代最细粒度切分算法一直沿用至今

其安装方式也比较简单,只要将资料提供好的分词器放入elasticsearch的插件目录中即可

在Kibana的Dev tools中可以使用下面的语法来测试IK分词器:

json 复制代码
POST /_analyze
{
    "analyze": "standard",
    "text": "Java"
}

语法说明:

  • Post:请求方式
  • /_analyze:请求路径,这里省略了地址,有Kibana帮我们补充
  • 请求参数,json风格:
    • analyze:分词器类型,这里是默认的standard分词器
    • text:要分词的内容

Ik分词器允许我们配置扩展词典来增加自定义的词库:

1.4、基础概念

elasticsearch中的文档数据会被序列化为json格式后存储在elasticsearch中

索引(index):相同类型的文档的集合

映射(mapping):索引中文档的字段约束信息,类似表的结构约束

2、索引库操作

2.1、Mapping映射属性

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

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

Elasticsearch提供的所有API都是RestFul的接口,遵循RestFul的基本规范:

2.2、索引库操作

创建索引库和mapping的请求语法如下:

查看索引库语法:

json 复制代码
GET /索引库名

删除索引库:

DELETE /索引库名

修改索引库:索引库和mapping一旦创建无法修改,但是可以添加新的字段,语法如下:

json 复制代码
PUT /索引库名/_mapping
{
	"properties": {
		"新字段名":{
			"type": "integer"
		}
	}
}

3、文档操作

3.1、文档CRUD

新增文档的请求格式如下:{json文档}

查看文档请求格式:

GET /索引库名/_doc/文档id

删除索引库的请求格式:

DELETE /索引库名/_doc/文档id

修改文档:

3.2、批量处理

Elasticsearch中允许通过一次请求中携带多次文档操作,也就是批量处理,语法格式如下:

4、JavaRestClient

4.1、客户端初始化

1、引入es的RestHighLevelClient依赖:

xml 复制代码
<dependency>
	<groupId>org.elasticsearch.client</groupId>
    <artifactId>elasticsearch-rest-high-level-client</artifactId>
</dependency>

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

XML 复制代码
  <properties>
      <maven.compiler.source>11</maven.compiler.source>
      <maven.compiler.target>11</maven.compiler.target>
      <elasticsearch.version>7.12.1</elasticsearch.version>
  </properties>

3、初始化RestHighLevelClient:

初始化的代码如下:

Java 复制代码
RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(
        HttpHost.create("http://192.168.150.101:9200")
));
4.2、商品表Mapping映射
JSON 复制代码
PUT /items
{
  "mappings": {
    "properties": {
      "id": {
        "type": "keyword"
      },
      "name":{
        "type": "text",
        "analyzer": "ik_max_word"
      },
      "price":{
        "type": "integer"
      },
      "stock":{
        "type": "integer"
      },
      "image":{
        "type": "keyword",
        "index": false
      },
      "category":{
        "type": "keyword"
      },
      "brand":{
        "type": "keyword"
      },
      "sold":{
        "type": "integer"
      },
      "commentCount":{
        "type": "integer",
        "index": false
      },
      "isAD":{
        "type": "boolean"
      },
      "updateTime":{
        "type": "date"
      }
    }
  }
}
4.3、索引库操作

创建索引库的JavaAPI与RestFul接口API对比:

索引库操作的基本步骤:

1、创建XxxIndexRequest。XXX是Create、Get、Delete

2、准备请求参数(Create时需要)

3、发送请求。调用RestHighLevelClient#indices)

4.4、文档操作

新增文档:

JSON 复制代码
POST /{索引库名}/_doc/1
{
    "name": "Jack",
    "age": 21
}

查询文档:

JSON 复制代码
GET /{索引库名}/_doc/{id}

删除文档:

JSON 复制代码
DELETE /hotel/_doc/{id}

修改文档:

在RestClient的API中,全局修改和新增的API完全一致,判断依据是ID:

  • 如果是新增时,ID已经存在,则修改
  • 如果新增时,ID不存在,则新增
4.5、批处理

在之前的案例中,我们都是操作单个文档。而数据库中的商品数据实际会达到数十万条,某些项目中可能达到数百万条。

我们如果要将这些数据导入索引库,肯定不能逐条导入,而是采用批处理方案。常见的方案有:

  • 利用Logstash批量导入
    • 需要安装Logstash
    • 对数据的再加工能力较弱
    • 无需编码,但要学习编写Logstash导入配置
  • 利用JavaAPI批量导入
    • 需要编码,但基于JavaAPI,学习成本低
    • 更加灵活,可以任意对数据做再加工处理后写入索引库

批处理代码流程与之前类似,只不过构建请求会用到一个名为BulkRequest来封装普通的CRUD请求

5、DSL查询

Elasticsearch提供DSL(Domain Specific Language)查询,就是以JSON格式来定义查询条件。类似:

DSL查询可以分为两大类:

  • 叶子查询:一般是在特定的字段里查询特定值,属于简单查询,很少单独使用
  • 复合查询:以逻辑方式组合多个叶子查询或者更改叶子查询的行为模式

在查询以后,还可以对查询的结果做处理,包括:

  • 排序:按照1个或多个字段值做排序
  • 分页:根据form和size做分页,类似MySQL
  • 高亮:对搜索结果中的关键字添加特殊样式,使其更醒目
  • 聚合:对搜索结果做数据统计以形成报表

5.1、快速入门

基于DSL的查询语法如下:

!

5.2、叶子查询

叶子查询还可以进一步细分,常见的有:

  • **全文检索(full text)**查询:利用分词器对用户输入内容分词,然后去词条列表中匹配。例如:
    • match_query
    • multi_match_query
  • 精确查询 :不对用户输入内容分词,直接精确匹配,一般是查找keyword、数值、日期、布尔类型等。例如:
    • ids
    • range:根据数值范围查询,可以是日期的范围
    • term:根据词条精确匹配,一般搜索keyword类型、数值类型、布尔类型、日期类型字段
  • 地理(geo)查询 :用于搜索地理位置,搜索方式很多。例如:
    • geo_distance
    • geo_bounding_box

5.3、复合查询

复合查询大致可以分为两类:

  • 第一类:基于逻辑运算组合叶子查询,实现组合条件,例如:
    • bool(布尔查询)
  • 第二类:基于某种算法修改查询时达到文档相关性算分,从而改变文档排名。例如:
    • function_score
    • dis_max

布尔查询是一个或多个查询子句的组合。子查询的组合方式有:

  • must:必须匹配每一个子查询,类似"与"
  • should:选择性匹配子查询,类似"或"
  • must_not:必须不匹配,不参与算分,类似"非"
  • filter:必须匹配,不参与算分

5.4、排序和分页

Elasticsearch支持对搜索结果排序,默认是根据相关度算分(_score)来排序,可以排序字段类型有:keyword类型、数值类型、地理坐标类型、日期类型等。

深度分页问题

Elasticsearch的数据一般会采用分片存储,也就是把一个索引中的数据分为N份,存储到不同节点上。查询数据时需要汇总各个分片的数据

针对深度分页,ES提供了两种解决方案:

  • search after:分页时需要排序,原理是上一次的排序值开始,查询下一页数据。官方推荐使用的方式
    • 优点:没有查询上限,支持深度分页
    • 缺点:只能向后逐页查询,不能随机翻页
    • 场景:数据迁移、手机滚动查询
  • scorll:原理将数据形成快照,保存在内存。官方已经不推荐使用。

5.5、高亮显示

高亮显示:就是在搜索结果中把搜索关键字突出显示。

6、JavaRestClient查询

6.1、快速入门

数据搜索的Java代码我们分为两部分:

  • 构建并发起请求
  • 解析查询结果

解析查询结果的API:

6.2、构建查询条件

在JavaRestAPI中,所有类型的query查询条件都是由QueryBuilders来构建的:

全文检索的查询条件构造APi如下:

精确查询的查询条件构造API如下:

布尔查询的查询条件构造API如下:

6.3、排序和分页

与query类似,排序和分页参数都是基于request.source()来设置:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

6.4、高亮显示

高亮显示的条件构造API如下:

高亮显示的结果解析API如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

7、数据聚合

聚合

(aggregations)可以实现对文档数据的统计、分析、运算。聚合常见的有三类:

  • 桶(Bucket)聚合:用来对文档做分组
    • TermAggregation:按照文档字段值分组
    • Date Histogram:按照日期阶梯分组,例如一周为一组,或者一月为一组
  • 度量(Metric)聚合:用以计算一些值,比如:最大值、最小值、平均值等
    • Avg
    • Max
    • Min
    • Stats:同时求max、min、avg、sum等
  • 管道(pipeline)聚合:其它聚合的结果为基础做聚合

注意:参与聚合的字段必须是keyword、数值、日期、布尔类型的字段

7.1、DSL聚合

我们要统计所有商品中共有哪些商品分类,其实就是以分类(category)字段对数据分组。category值一样的放在同一组,属于Bucket聚合中的Term聚合。

默认情况下,Bucket聚合是对索引库的所有文档做聚合,我们可以限定要聚合的文档范围,只要添加query条件即可。

例如,我想知道价格高于3000元的手机品牌有哪些:

除了对数据分组(Bucket以外),我们还可以对每一个Bucket内的数据进一步做数据计算和统计。

例如:我想知道手机有哪些品牌,每个品牌的价格最大值、最小值、平均值

7.2、RestClient聚合

相关推荐
Natural_yz2 小时前
大数据学习17之Spark-Core
大数据·学习·spark
Karoku0663 小时前
【企业级分布式系统】ELK优化
运维·服务器·数据库·elk·elasticsearch
莫叫石榴姐3 小时前
数据科学与SQL:组距分组分析 | 区间分布问题
大数据·人工智能·sql·深度学习·算法·机器学习·数据挖掘
魔珐科技4 小时前
以3D数字人AI产品赋能教育培训人才发展,魔珐科技亮相AI+教育创新与人才发展大会
大数据·人工智能
上优5 小时前
uniapp 选择 省市区 省市 以及 回显
大数据·elasticsearch·uni-app
szc17675 小时前
docker 相关命令
java·docker·jenkins
samLi06206 小时前
【更新】中国省级产业集聚测算数据及协调集聚指数数据(2000-2022年)
大数据
Mephisto.java6 小时前
【大数据学习 | Spark-Core】Spark提交及运行流程
大数据·学习·spark
EasyCVR7 小时前
私有化部署视频平台EasyCVR宇视设备视频平台如何构建视频联网平台及升级视频转码业务?
大数据·网络·音视频·h.265
hummhumm7 小时前
第 22 章 - Go语言 测试与基准测试
java·大数据·开发语言·前端·python·golang·log4j