-
Elasticsearch 是一个开源的搜索引擎,建立在一个全文搜索引擎库 Apache Lucene™ 基础之上。
- 一个分布式的实时文档存储,每个字段可以被索引与搜索
- 一个分布式实时分析搜索引擎
- 能胜任上百个服务节点的扩展,并支持 PB 级别的结构化或者非结构化数据
-
Elasticsearch是分布式的搜索、分析引擎,是Elastic Stack的核心。
-
Logstash和Beats用于收集、聚合、丰富数据。
-
Kibana用于数据可视化管理。
-
索引、搜索、分析,这些都是在Elasticsearch上进行的。ElasticSearch为所有类型(结构化/非结构化文本、数字数据、地理空间数据)的数据提供近乎实时的搜索和分析。透过数据检索和信息聚合,能够发现数据的趋势和模式。由于分布式的特性,即使数据增长,ElasticSearch的部署也能随之无缝增长。
-
ElasticSearch可用于许多地方:
- 在网页上的搜索框
- 存储并分析日志、度量和安全事件数据
- 使用机器学习实时自动根据数据的行为建模
- 使用ElasticSearch作为存储引擎自动化业务工作流
- 把ElasticSearch当作地理信息系统(GIS)来管理、集成和分析空间信息
- 使用Elasticsearch作为生物信息学研究工具存储和处理遗传数据
无论用ElasticSearch来解决什么问题,在Elasticsearch中处理数据、文档和索引的方式都是相同的。
-
速度快,通过有限状态转换器实现了用于全文检索的倒排索引,实现了用于存储数值数据和地理位位置数据的BKD树,以及用于分析的列存储
-
可扩展性,水平扩展,处理海量事件,自动管理索引和查询在集群中的分布方式
-
弹性,检测并确保集群和数据的安全性和可用性
-
数据类型多样,能够执行及合并多种类型的搜索(结构化数据、非结构化数据、地理位置、指标)
-
场景:应用搜索、安全分析、指标或日志分析
-
ElasticSearch 是分布式数据库,允许多台服务器协同工作,每台服务器可以运行多个实例。单个实例称为一个节点(node),一组节点构成一个集群(cluster)。
-
分片是底层的工作单元,文档保存在分片内,分片又被分配到集群内的各个节点里,每个分片仅保存全部数据的一部分。
-
索引 Index、类型 Type 和文档 Document
对比我们比较熟悉的 MySQL 数据库:
index → db
type → table
document → row如果我们要访问一个文档元数据应该包括index/type/id 这三种类型
安装
-
安装ElasticSearch
-
官方文档 https://www.elastic.co/cn/downloads/elasticsearch
-
CSDN https://blog.csdn.net/UbuntuTouch/article/details/99413578
-
在终端启动 elasticsearch 在http://127.0.0.1:9200/ 得到对应的json文件则表示成功 { "name" : "admin", "cluster_name" : "elasticsearch_cjl", "cluster_uuid" : "jfw0X9fLQoeFsDfBSR95lw", "version" : { "number" : "7.13.2", "build_flavor" : "default", "build_type" : "tar", "build_hash" : "4d960a0733be83dd2543ca018aa4ddc42e956800", "build_date" : "2021-06-10T21:01:55.251515791Z", "build_snapshot" : false, "lucene_version" : "8.8.2", "minimum_wire_compatibility_version" : "6.8.0", "minimum_index_compatibility_version" : "6.0.0-beta1" }, "tagline" : "You Know, for Search" }
-
-
安装 Kinbana
-
官方文档 https://www.elastic.co/cn/downloads/kibana
-
CSDN https://elasticstack.blog.csdn.net/article/details/99433732
-
在终端启动Kibana 在http://127.0.0.1:5601 能够进入 左侧的Management中的Dev Tools中输入 GET / 得到和上面一样的JSON文件
-
入门
- config 包含配置文件
- elasticsearch.yml 是主要配置文件
- log4j2.properties 日志记录配置文件
- plugins 安装自定义插件
- 加载默认安装的模块。最重要的如下。
- aggs-matrix-stats: 提供对**聚合矩阵( Aggregation Matrix)**统计信息的支持。
- analysis-common: 这是Elasticsearch 的通用分析器( Common Analyzer),它扩展了Elasticsearch 的语言处理能力。
- ingest-common: 这些包含采集(Ingest) 模块的常见功能。
- lang-expression/ang mustache/lang painless:这些是Elasticsearch默认支持的脚本语言。
- mapper-extras:这提供了一种额外的映射器(Mapper)类型,例如token count和scaled float
- parent-join:这提供了额外的查询,例如has_ children 和has parent。
- percolator:提供过滤器(Percolator) 功能。
- rank-eval: 为实验等级评估API提供支持。这些用于评估查询的得分。
- reindex: 这提供了对重新索引(Reindex) 操作(通过查询进行重新索引/更新)的支持。
- x-pack- *:所有xpack模块的激活都依赖于订阅。
- ES未配置,会在本地主机127.0.0.1上绑定以下端口
- 9300: 用于内部节点内通信
- 9200: 用于HTTP REST API
数据格式
-
正排索引(传统) 和 倒排索引(通过关键字查主id 关联文章)
-
Elasticsearch 是面向文档型数据库,一条数据在这里就是一个文档。为了方便大家理解,
我们将 Elasticsearch 里存储文档数据和关系型数据库 MySQL 存储数据的概念进行一个类比
ES 里的 Index 可以看做一个库,而 Types 相当于表,Documents 则相当于表的行。这里 Types 的概念已经被逐渐弱化,Elasticsearch 6.X 中,一个 index 下已经只能包含一个type,Elasticsearch 7.X 中, Type 的概念已经被删除了。
索引操作
- 创建索引 PUT
- number_of_shards: 控制组成索引的分片的数量,每个分片最多存储232个文档
- number_of_replicas: 控制复制副本的数量
- POST 没有幂等性 每次执行返回的结果一样
// 创建
PUT /myindex
{
"settings": {
"number_of_shards": 2,
"number_of_replicas": 1
}
}
// 返回
{
"acknowledged" : true, //响应结果
"shards_acknowledged" : true, //分片操作成功 分片数默认一片
"index" : "myindex" //索引名称
}
// 重复创建 如果已经存在
{
"error" : {
"root_cause" : [
{
"type" : "resource_already_exists_exception",
"reason" : "index [myindex/AE0MeZWHRUi7F-uw6HBkQA] already exists",
"index_uuid" : "AE0MeZWHRUi7F-uw6HBkQA",
"index" : "myindex"
}
],
"type" : "resource_already_exists_exception",
"reason" : "index [myindex/AE0MeZWHRUi7F-uw6HBkQA] already exists",
"index_uuid" : "AE0MeZWHRUi7F-uw6HBkQA",
"index" : "myindex"
},
"status" : 400
}
- 获取索引 GET
- 查看所有索引 GET /_cat/indices?v
- health 当前服务器健康状态: green(集群完整) yellow(单点正常、集群不完整) red(单点不正常)
- status 索引打开、关闭状态
- index 索引名
- uuid 索引统一编号
- pri 主分片数量
- rep 副本数量
- docs.count 可用文档数量
- docs.deleted 文档删除状态(逻辑删除)
- store.size 主分片和副分片整体占空间大小
- pri.store.size 主分片占空间大小
GET /myindex
{
"myindex" : { //索引名
"aliases" : { }, //别名
"mappings" : { }, //映射
"settings" : { //设置
"index" : {
"routing" : {
"allocation" : {
"include" : {
"_tier_preference" : "data_content"
}
}
},
"number_of_shards" : "2", //主分片数
"provided_name" : "myindex",
"creation_date" : "1624355873667", //创建时间
"number_of_replicas" : "1", //副分片数
"uuid" : "tEeewdKVTaq_6SrzhkXE5A", //唯一标识
"version" : { //版本
"created" : "7130299"
}
}
}
}
}
//查看所有索引
GET _cat/indices?v
health status index uuid pri rep docs.count docs.deleted store.size pri.store.size
yellow open myindex tEeewdKVTaq_6SrzhkXE5A 2 1 0 0 416b 416b
- 删除索引
// 删除索引
DELETE /myindex
// 输出
{
"acknowledged" : true
}
文档操作
- 创造文档
//创造文档
POST /myindex/_doc
{
"title":"小米手机",
"category":"小米", "images":"http://www.gulixueyuan.com/xm.jpg", "price":3999.00
}
{
"_index" : "myindex", //索引
"_type" : "_doc", //类型-文档
"_id" : "NOo7M3oBOoE5b8zX1vLH", 唯一标识符
"_version" : 1, //版本
"result" : "created", //创建成功
"_shards" : {
"total" : 2, //分片总数
"successful" : 1, //成功
"failed" : 0
},
"_seq_no" : 0,
"_primary_term" : 1
}
//由于没有指定数据唯一性标识(ID),默认情况下,ES 服务器会随机 生成一个。
POST /myindex/_doc/1 //自己指定ID 可以用PUT
{...}
- 查看文档
//查看文档 需要uid 主键查询
GET /myindex/_doc/1
{
"_index" : "myindex", //索引
"_type" : "_doc", //文档类型
"_id" : "1",
"_version" : 1,
"_seq_no" : 2,
"_primary_term" : 1,
"found" : true, //表示找到
"_source" : { //文档源信息
"title" : "小米手机",
"category" : "小米",
"images" : "http://www.gulixueyuan.com/xm.jpg",
"price" : 3999.0
}
}
// 查看所有的 全局查询 返回所有找到的
GET /myindex/_search
- 修改文档
// 全部覆盖 全量数据更新
POST /myindex/_doc/1
{
"title":"华为手机",
"category":"华为",
"images":"http://www.gulixueyuan.com/hw.jpg",
"price":4999.00
}
{
"_index" : "myindex",
"_type" : "_doc",
"_id" : "1",
"_version" : 2,
"result" : "updated",
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 3,
"_primary_term" : 1
}
// 局部更新
POST /myindex/_update/1
{
"doc":{
"title":"苹果手机"
}
}
- 删除文档
- 删除一个文档不会立即从磁盘上移除,它只是被标记成已删除(逻辑删除)。
- 一般删除数据都是根据文档的唯一性标识进行删除,实际操作时,也可以根据条件对多条数据进行删除
DELETE /myindex/_doc/1
{
"_index" : "myindex",
"_type" : "_doc",
"_id" : "1",
"_version" : 5,
"result" : "deleted",
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 6,
"_primary_term" : 1
}
//插入多条数据
POST /myindex/_doc/1
{
"title":"小米手机",
"category":"小米",
"images":"http://www.gulixueyuan.com/xm.jpg",
"price":4000.00
}
POST /myindex/_doc/2
{
"title":"华为手机",
"category":"华为",
"images":"http://www.gulixueyuan.com/xm.jpg",
"price":4000.00
}
//删除符合条件的
POST /myindex/_delete_by_query
{
"query":{
"match":{
"price":4000.00
}
}
}
// 返回结果
{
"took" : 436, //耗时
"timed_out" : false, //是否超时
"total" : 2, //总数
"deleted" : 2, //删除数量
"batches" : 1,
"version_conflicts" : 0,
"noops" : 0,
"retries" : {
"bulk" : 0,
"search" : 0
},
"throttled_millis" : 0,
"requests_per_second" : -1.0,
"throttled_until_millis" : 0,
"failures" : [ ]
}
映射操作
- 有了索引库,相当于有了数据库中的database,需要建立索引中的映射,类似于数据库中的表结构 需要设置字段名称,类型,长度,约束等
- 创建映射
- 字段名:任意填写,下面指定许多属性,例如:title、subtitle、images、price
- type:类型,Elasticsearch中支持的数据类型非常丰富,说几个关键的:
- String 类型,又分两种:
- **text:可分词 **
- keyword:不可分词,数据会作为完整字段进行匹配
- Numerical:数值类型,分两类 :
- 基本数据类型:long、integer、short、byte、double、float、half_float
- 浮点数的高精度类型:scaled_float
- Date:日期类型
- Array:数组类型
- Object:对象
- String 类型,又分两种:
- index:是否索引,默认为true,也就是说你不进行任何配置,所有字段都会被索引
- true:字段会被索引,则可以用来进行搜索
- false:字段不会被索引,不能用来搜索
- store:是否将数据进行独立存储,默认为 false
- 原始的文本会存储在_source 里面,默认情况下字段是从_source 里面提取出来的。当然你也可以独立的存储某个字段,只要设置 “store”: true 即可,获取独立存储的字段要比从_source 中解析快得多,但是也会占用 更多的空间,所以要根据实际业务需求来设置。
- analyzer:分词器,这里的 ik_max_word 即使用 ik 分词器
PUT /student/_mapping
{
"properties": {
"name":{ //字段名
"type": "text",
"index": true
},
"sex":{
"type": "text",
"index": false
},
"age":{
"type": "long",
"index": false
}
}
}
- 查看映射
GET /student/_mapping
{
"student" : {
"mappings" : {
"properties" : {
"age" : {
"type" : "long",
"index" : false
},
"name" : {
"type" : "text"
},
"sex" : {
"type" : "text",
"index" : false
}
}
}
}
}
- 索引映射关联
PUT /student1
{
"settings": {},
"mappings": {
"properties": {
"name":{
"type": "text",
"index": true
},
"sex":{
"type": "text",
"index": false
},
"age":{
"type": "long",
"index": false
}
}
}
}
高级查询
单个字段匹配查询 match
可以在多个字段中查询 multi_match
关键字精确查询 term、多关键字精确查询 terms
bool
把各种其它查询通过must
(必须 )、must_not
(必须不)、should
(应该)的方 式进行组合范围查询 找出落在指定区间的数字或时间 range
模糊查询 返回包含与搜索字符相似的字词的文档 fuzzy
单字段排序 sort order desc
分页查询 from size
聚合查询 类似与关系型数据库中的 group by aggs
- 插入文档
POST /student/_doc/1001
{
"name":"zhangsan", "nickname":"zhangsan", "sex":"男",
"age":30
}
POST /student/_doc/1002
{
"name":"lisi", "nickname":"lisi", "sex":"男", "age":20
}
POST /student/_doc/1003
{
"name":"wangwu", "nickname":"wangwu", "sex":"女",
"age":40
}
POST /student/_doc/1004
{
"name":"zhangsan1", "nickname":"zhangsan1", "sex":"女",
"age":50
}
POST /student/_doc/1005
{
"name":"zhangsan2", "nickname":"zhangsan2", "sex":"女",
"age":30
}
- 查询所有文档
GET /student/_search
{
"query":{
"match_all":{}
}
}
// 命中5条记录
{
"took" : 431,
"timed_out" : false, //是否超时
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0, //忽略
"failed" : 0
},
"hits" : { //搜索命中结果
"total" : { //搜索条件匹配的文档总数
"value" : 5, //总命中计数的值
"relation" : "eq" //eq:计数准确 gte:计数不准确
},
"max_score" : 1.0, //匹配度分值
"hits" : [ //命中结果集合
{
...
- 匹配查询 query
- 单个字段匹配查询 match
GET /student/_search
{
"query":{
"match":{
"name":"zhangsan"
}
}
}
- multi_match 可以在多个字段中查询
// 多个匹配
GET /student/_search
{
"query":{
"multi_match":{
"query":"zhangsan",
"fields":["name","nickname"]
}
}
}
- 关键字精确查询 term、多关键字精确查询 terms
// 关键字精确查询
GET /student/_search
{
"query": {
"term": {
"name": {
"value": "zhangsan"
}
}
}
}
// 多个匹配
GET /student/_search
{
"query": {
"terms": {
"name": ["zhangsan","lisi"]
}
}
}
- 过滤字段
- includes: 来指定想要显示的字段
- excludes:不想显示的字段
// 过滤字段
GET /student/_search
{
"_source": {
"includes": ["name","nickname"]
},
"query": {
"terms": {
"nickname": ["zhangsan"]
}
}
}
bool
把各种其它查询通过must
(必须 )、must_not
(必须不)、should
(应该)的方 式进行组合
// 组合查询
GET /student/_search
{
"query": {
"bool":{
"must":[
{
"match":{
"name":"zhangsan"
}
}
],
"must_not":[
{
"match":{
"age":"40"
}
}
],
"should":[
{
"match":{
"sex":"男"
}
}
]
}
}
}
- 范围查询 找出落在指定区间的数字或时间 range
- gt 大于 gte 大于等于 lt 小于 lte 小于等于
// 范围查询
GET /student/_search
{
"query": {
"range": {
"age": {
"gte": 30,
"lte": 35 }
}
}
}
- 模糊查询 返回包含与搜索字符相似的字词的文档 fuzzy
- 编辑距离是将一个术语转换为另一个术语所需的一个字符更改的次数。
- 更改字符(box → fox) 、删除字符(black → lack)、插入字符(sic → sick)、转置两个相邻字符(act → cat)
- 为了找到相似的术语,fuzzy 查询会在指定的编辑距离内创建一组搜索词的所有可能的变体 或扩展。然后查询返回每个扩展的完全匹配。 通过 fuzziness 修改编辑距离。一般使用默认值 AUTO,根据术语的长度生成编辑距离。
// 模糊查询
GET /student/_search
{
"query": {
"fuzzy": {
"name": {
"value": "zhangsan"
}
}
}
}
- 单字段排序
- sort 可以让我们按照不同的字段进行排序,并且通过 order 指定排序的方式。desc 降序,asc 升序。
// 单、多字段排序
GET /student/_search
{
"query":{
"match_all":{
}
},
"sort":[{
"age":{
"order":"desc"
}
}]
}
GET /student/_search
{
"query":{
"match_all":{
}
},
"sort":[
{
"age":{
"order":"desc"
}
},
{
"_score":{
"order":"desc"
}
}]
}
- 高亮查询 highlight属性
- pre_tags:前置标签
- post_tags:后置标签
- fields:需要高亮的字段
- title:这里声明 title 字段需要高亮,后面可以为这个字段设置特有配置,也可以空
GET /student/_search
{
"query": {
"match": {
"name": "zhangsan"
}
},
"highlight": {
"pre_tags": "<font color='red'>",
"post_tags": "</font>",
"fields": {
"name": {}
}
}
}
- 分页查询
- from:当前页的起始索引,默认从 0 开始。 from = (pageNum - 1) * size
- size:每页显示多少条
GET /student/_search
{
"query": {
"match_all": {}
},
"sort": [{
"age": {
"order": "desc"
}
}],
"from": 0,
"size": 2
}
- 聚合查询 类似与关系型数据库中的 group by,当然还有很 多其他的聚合,例如取最大值、平均值等等。
GET /student/_search
{
"aggs":{
"max_age":{
"max":{"field":"age"}
}
},
"size":0
}
// 对某个字段的值进行去重之后再取总数
GET /student/_search
{
"aggs":{
"distinct_age":{
"cardinality":{"field":"age"}
}
},
"size":0
}
// stats 聚合,对某个字段一次性返回 count,max,min,avg 和 sum 五个指标
把上面的cardinality 换成 stats
- 桶聚合查询
- terms 聚合,分组统计
GET /student/_search
{
"aggs":{
"age_groupby":{
"terms":{"field":"age"}
}
},
"size":0
}