【ES系列】ES的数据结构与DSL语法
ES的数据结构与DSL语法
- 数据结构部分
- 正向索引与倒排索引
- 定义
- 结构
- 分词(keyword)
- DSL语句
- 常用DSL语句
- 索引部分
- 创建索引
- 查看es所有索引
- 查看单个索引
- 删除索引
- 文档部分
- 创建文档
- 批量执行
- 查询文档
- 查询操作DSL
- 查询验证
- 条件查询
- match/match_phrase(完全匹配)
- match_all并且排序
- 多条件查询
- 聚合分页查询
- 结语
本篇章将围绕ES的基本功能、实现原理与性能优化这三个方面,使读者能够逐渐深入了解ES的特点与能力。本篇所用的版本为7.10.2同kibana版本,需要注意的是,es与kibana至少在大版本上要保持一致,否则功能上会有兼容性问题。
ES的特征
分布式:ES是分布式的开源搜索和分析引擎,基于Apache Lucene开发而成,适用于所有类型的数据,包括文字、数字、地理空间、结构化和非结构化数据
1.1. 分布式架构:
之后的章节里,会逐步讲解ES的架构内容。1.2 集群(Cluster)
1.3 节点(Node)
1.4 副本(Replica):副本,replica主要用来保证高可用(故障转移)、数据备份、增强高吞吐的并行搜索
1.5 分片(Shard):是非常重要的点,它允许ES跨分片(可以是多个节点)分布和并行操作,从而提高性能与吞吐量存储方式:不同于数据库中的行列存储形式,ES将信息存储为JSON文档的数据结构
全文检索:全文检索功能是ES广泛运用的主要原因,由于分布式的特点,存储文档会分布整个集群中,因此搜索效率非常高
数据结构部分
ES通过倒排索引的数据结构做到快速索引和全文检索,该结构支持非常快速的全文本搜索。
一般情况下,ES默认对每个字段中的所有数据建立索引,并且每个索引字段都具备专有的优化数据结构
例如,文本字段是存储在倒排索引中,而数字或地理信息的字段存储在BKD树中,BKD树可以理解为多维度的树形结构。
数据类型 | 数据结构 |
---|---|
text/keyword | 倒排索引 |
数字/地理位置 | BKD树 |
正向索引与倒排索引
定义
倒排索引的英文是Inverted index (link),是有转换的意思。被翻译成倒排我觉得有两个原因:
- 由于倒排索引不同于关系型数据库,通过id去查找内容,而在ES中是通过keyword,也就是文档内容去查找具体文件
- ES中还有个正排索引Forword Index表中记录文档中每个字的位置信息,查找时扫描表中每个文档中字的信息直到找出所有包含查询关键字的文档。
结构
下面针对两种索引举例(index_01: this is elasticsearch / index_02:elasticsearch query)
倒排索引
关键词 | 文档id |
---|---|
this | index_01 |
is | index_01 |
elasticsearch | index_01, index_02 |
query | index_02 |
正排索引
文档id | 关键词 |
---|---|
index_01 | this, is, elasticsearch |
index_02 | elasticsearch, query |
分词(keyword)
ES对于文档内容或者某一段文本,都会进行分词,也就是把一段话中的单词进行拆分。分词的效果将直接影响倒排索引的搜索能力。
所以选择合适的分词是十分重要的。对于不同语言,分词器也是不同的。比如英文会使用Standard, ngram等,中文可选ik分词器,常用有ik_smart_max_word。
这里以英文举例查看不同分词器的效果
在ngram_tokenizer的格式中,可以设置最大最小步长,
// An highlighted block
"tokenizer": {"my_tokenizer": {"type": "ngram","min_gram": 1,"max_gram": 2,"token_chars": ["letter","digit"]}
}
以"Qu Cdn"为例,使用ngram分词
// An highlighted block
{"tokenizer": "ngram","text": "Qu Cdn"
}
以下是分词的返回结果,可以看到颗粒度限制在1-2的长度,甚至还包括空格
// An highlighted block
{"tokens": [{"token": "Q","start_offset": 0,"end_offset": 1,"type": "word","position": 0},{"token": "Qu","start_offset": 0,"end_offset": 2,"type": "word","position": 1},{"token": "u","start_offset": 1,"end_offset": 2,"type": "word","position": 2},{"token": "u ","start_offset": 1,"end_offset": 3,"type": "word","position": 3},{"token": " ","start_offset": 2,"end_offset": 3,"type": "word","position": 4},{"token": " C","start_offset": 2,"end_offset": 4,"type": "word","position": 5},{"token": "C","start_offset": 3,"end_offset": 4,"type": "word","position": 6},{"token": "Cd","start_offset": 3,"end_offset": 5,"type": "word","position": 7},{"token": "d","start_offset": 4,"end_offset": 5,"type": "word","position": 8},{"token": "dn","start_offset": 4,"end_offset": 6,"type": "word","position": 9},{"token": "n","start_offset": 5,"end_offset": 6,"type": "word","position": 10}]
}
使用Standard分词情况,返回的结果就是按空格分开
// An highlighted block
{"tokens": [{"token": "Qu","start_offset": 0,"end_offset": 2,"type": "<ALPHANUM>","position": 0},{"token": "Cdn","start_offset": 3,"end_offset": 6,"type": "<ALPHANUM>","position": 1}]
}
分词器的不同,ES创建的倒排索引结构也将不同,进而编写的搜索条件也将不同。
这里需要考虑的是,分词器的分词颗粒度越细,倒排索引的结构也就越大。之后就是匹配度与性能的鱼和熊掌的问题。
所以要根据实际业务选择合适的分词器,下一部分将展示不同的elasticsearch-dsl语句。
DSL语句
同其他类型的数据库一样,ES也有自己的query语言,其搜索结构都是由json串组合构成请求体发送。
常用DSL语句
索引部分
创建索引
创建索引最关键的部分就是settings跟mappings的部分,settings设置包括分片副本,分词器等内容
mappings就是index所包含的映射结构与内容,比如mappings中可以是否为动态映射。
PUT /index03
{"settings": {"analysis": {"analyzer": {"ngram_analyzer": {"tokenizer": "ngram_tokenizer","filter": ["lowercase"]}},"tokenizer": {"ngram_tokenizer": {"type": "ngram","min_gram": 3,"max_gram": 3}}},"mappings":{"dynamic": false,"properties":{"object":{"attr":{"name": {"type": "keyword"},"site": {"type": "long"},"filepath": {"type": "text"},"filename": {"type": "keyword"},"date": {"type": "keyword"}}}}}}
}
需要注意的是,如果一个index中field太多会导致映射爆炸的问题,所以需要设定index.mapping.total_fileds_limit属性
查看es所有索引
GET /_cat/indices?v
查看单个索引
GET /index03
删除索引
DELETE /index03
文档部分
创建文档
POST /index03/_doc/7
{"name" : "kibana","site" : 212121,"date" : "20230101","filepath" : "/a/b/k/d/e/f","filename" : "nothing"
}
批量执行
POST /index03/_doc/_bulk
{"index":{"_id":7}}
{"name":"elastic","site":24,"filepath":"/a/b/k/d/e/f"}
{"index":{"_id":8}}
{"name":"search","site":-11,"filepath":"/a/b/k/d/e/f"}
{"index":{"_id":9}}
{"name":"stack","site":0,"filepath":"/a/b/k/d/e/f"}
查询文档
GET /index03/_doc/7
返回值
{"_index" : "index03","_type" : "_doc","_id" : "7","_version" : 1,"_seq_no" : 6,"_primary_term" : 1,"found" : true,"_source" : {"name" : "kibana","site" : 212121,"date" : "20230101","filepath" : "/a/b/k/d/e/f","filename" : "nothing"}
}
查询操作DSL
DSL Query的分类
Elasticsearch提供了基于JSON的DSL(Domain Specific Language)来定义查询。常见的查询类型包括:
查询所有:查询出所有数据,一般测试用。例如:match_all
全文检索(full text)查询:利用分词器对用户输入内容分词,然后去倒排索引库中匹配。例如:
match_query, multi_match_query
精确查询:根据精确词条值查找数据,一般是查找keyword、数值、日期、boolean等类型字段。例如:
ids, range, term
地理(geo)查询:根据经纬度查询。例如:
geo_distance, geo_bounding_box
复合(compound)查询:复合查询可以将上述各种查询条件组合起来,合并查询条件。例如:
bool, function_score
查询验证
这是比较重要的一个点,有些时候语句执行出错,需要排查是数据问题,还是搜索语法的问题。
比如我这里举例在文档里找indexname为killbill的数据,但实际没有indexname这个field(类似mysql的column)
GET /index03/_doc/_validate/query?explain
{"query":{"match":{"indexname":"killbill"}}
}
如果语法是正确的话,会返回
{"_shards" : {"total" : 1,"successful" : 1,"failed" : 0},"valid" : true,"explanations" : [{"index" : "index03","valid" : true,"explanation" : """+MatchNoDocsQuery("unmapped fields [indexname]") #*:*"""}]
}
这里显示语法检查是正确的,并且会提示mappings里面没有indexname这个field
是一个非常好用的语法
条件查询
这里主要介绍几种查询的语法格式,相同语法格式会合并,就是替换关键词就行。比如match可以换成match_phrase,语法格式上没有区别,只是query下的搜索关键词不同。
match/match_phrase(完全匹配)
match:分词后搜索。比如分词后有N个分词,只要匹配上其中一个就可以返回数据了
match_phrase:分词后搜索。与match不同的是,match_phase分出来的词必须全部在搜索结果中,且位置顺序是一样的。
GET /index03/_doc/_search
{"query":{"match":{"name":"AFIND"}}
}
match_all并且排序
GET /index03/_search
{"query":{"match_all":{}},"sort":{"site":{"order":"desc"}}
}
多条件查询
GET /index03/_search
{"query":{"bool":{ # 表示需要进行条件过滤"must":[{ #表示必须满足下面的条件,并且参与计算分值,常用的子句还有should,表示“或”的意思"wildcard":{"filename":"*bill"}},{"match":{"site": 10086}}]}}
}
聚合分页查询
需要注意的是,在聚合中,只能针对整型类的数据类型(byte,short,integer,long)
GET /index03/_search
{"aggs":{ #表示聚合操作"site_group":{ #聚合后分组名称,可以随便起"terms":{ #表示分组操作,也可以使用avg来求平均值"field":"site" #表示对哪一个字段进行分组}}},"size":0 #表示不查询原始数据,只查询分组结果
}
结语
本篇内容主要介绍了ES的入门知识点与常用操作的语法,之后会基于其内核Lucene以及分布式架构展开并且深入,并设计性能提升方案。
【ES系列】ES的数据结构与DSL语法相关推荐
- es入门 和 dsl语法部分讲解
ElasticSearch与Lucene的关系 Lucene可以被认为是迄今为止最先进.性能最好的.功能最全的搜索引擎库(框架) 但是想要使用Lucene,必须使用Java来作为开发语言并将其直接集成 ...
- ES系列09:基于词项的搜索 之 Term/Terms query
完整版[系统学ES系列]请移步公号! 带着问题学习才高效 Term-level queries 与 Full text queries 的主要区别是什么? Term-level queries 有哪些 ...
- ES系列、Elasticsearch Suggester API(自动补全)
1.概念 1.1 补全api主要分为四类 Term Suggester(纠错补全,输入错误的情况下补全正确的单词) Phrase Suggester(自动补全短语,输入一个单词补全整个短语) Comp ...
- Android开发 之 OpenGL ES系列(5--3D立体图形)
OpenGL ES系列(5--3D立体图形) 转自:http://www.guidebee.info/wordpress/archives/1554 前面的例子尽管使用了OpenGL ES 3D图形库 ...
- ES系列二之常见问题解决
一 更新ES信息报错 报错信息如下: Use ElasticsearchException.getFailedDocuments() for detailed messages [{yjZ8D0oB= ...
- ES系列:查看所有索引及其状态
命令行: curl -XGET 'localhost:9200/_cat/indices?v&pretty' 浏览器: http://localhost:9200/_cat/indices?v ...
- 台达DVP ES系列PLC与台达MS300变频器通讯程序
台达DVP ES系列PLC与台达MS300变频器通讯程序 器件:台达DVP ES系列的PLC,台达MS300系列变频器,昆仑通态,威纶通 功能:实现频率设定,启停控制,实际频率读取等. 资料:带注释P ...
- 台达DVP ES系列plc与3台台达MS300变频器通讯程序 实现频率设定,启停控制,实际频率读取等
台达DVP ES系列plc与3台台达MS300变频器通讯程序 器件:台达DVP ES系列的PLC,3台台达MS300系列变频器,昆仑通态 功能:实现频率设定,启停控制,实际频率读取等. 资料:带注释P ...
- 台达PLC ES系列与英威腾GD变频器通讯程序原创可直接用于生产的程序
台达PLC ES系列与英威腾GD变频器通讯程序原创可直接用于生产的程序,程序带注释,并附送触摸屏程序,有接线方式和设置,通讯地址说明等. 程序采用轮询,可靠稳定 器件:台达DVP 14ES的PLC,英 ...
最新文章
- XML 特殊字符处理和 CDATA
- 【Redis学习笔记】2018-07-11 Redis指令学习5
- Kubernetes — 容器设计模式
- android 入门-引用库项目
- 记录一下(session共享的文章,wcf记录一下学习地址,Firebug)
- C#使用Log4Net记录日志【转】
- Javascript开发的HTML5游戏的知识产权保护
- openvswitch patch port使用方法
- 笨办法学 Python · 续 练习 12:复习
- 读写分离方案_项目读写分离方案
- 逸管家中小企业未来的发展不可忽视人才战略
- unity3d 射击游戏BOSS行为代码
- CPU缓存侧信道攻击
- Java冒泡排序法 降序
- 调出鲜艳水彩日式油画风景照片的PS教程
- Linux Centos 7软件防火墙
- jquery选择器通配符_jQuery选择器不等于通配符
- 30ea是什么意思_数量单位EA是什么意思?EACH? 单位EA是什么意思
- arista 交换机镜像端口配置(将某一端口的数据转发到指定端口)
- 44000+ 人一夜之间失业:一拖二懒三不读书,不淘汰你淘汰谁?