ES基础知识和常用查询基础
ES基础理论和基础查询
ES
文章目录
ES概述:
是一个基于RESTful WEB接口并且构建在Apach Lucene之上的开源分布式搜索引擎,能够支持全部检索,结构化检索和数据分析的工具
ps:Lucene是一个开放源代码的全部搜索引擎工具包,,全文搜索的引擎机构
ES的特点
- 开源分布式的搜索引擎
- 高扩展,处理PB级结构化和非结构化的数据
- ES的存储形式为文件存储,每个字段都能被用作索引
- 支持全部检索和结构化检索
ES的参数基本概念
ps:可以参考我们elk平台
1.Index: ES索引–>存储数据的地方,类似于我们正常数据库中的database
2. Type: 文档类型–>类似于databse下面的n张表,每个Index下面会有多个type
3. Document: 文档数据,类似于database里面一行一行的数据
4.Fieled: ES的json类型的字段,相当于database中表的列(Column)
5. Mapping: 索引中文档的约束,列入字段类型的约束。类似于database中的表的结构(Schema)
6. DSL: DSL是ES提供json类型风格的请求语句,类似于sql语句(增删改查)
ES数据同步
同步双写
ps:将数据写入到mysql中同时也写入到ES中,两者数据是同步的
流程: 程序–>(写入Mysql/ES)
优点
- 业务逻辑简单,实现方便
缺点
1.硬编码:在需要写入mysql中,同时需要添加ES写入的代码
2.ES代码和业务代码混合一起,耦合性较强,不符合高内聚低耦合的思想
3.存在双写过程中写入失败,数据丢失的风险
4.业务功能性能和体验比较长,mysql性能本身不高,这时候在处理ES会导致性能更差
异步双写
ps: 通过引入消息队列的模式,例如(MQ),从而形成异步处理。两者处理不会在同一个节点下进行
流程: 程序–>分别写入MQ–>(写入Mysql/ES)
优点
- 性能高;
- 不存在丢数据的情况
缺点
- 硬编码问题:需要增加写入MQ的代码
- 业务耦合性也比较强,需要在处理Mysql的同时,也会要处理ES的问题
- 复杂度增加:系统中加入了MQ,使系统的复杂性增加
4.MQ的消费需要根据服务器的性能和MQ的队列配置,网络等因素影响,导致数据的写入会存在一定的延迟问题
异步双写(WORKE模式)
ps:不管是同步双写还是MQ异步双写,对代码的植入性都很强,可能会影响正常业务。如果系统对实时性要求不高的情况下,引入定时器的概念,在程序一定的时间内扫描mysql表相关变化的数据,然后逐条对变化的数据写入到ES中
流程: 程序–>Mysql数据库<–定时器(查询crud的数据)–>写入MQ
优点
- 耦合性比较低:不会对业务代码存在强耦合,影响正常业务功能
- 不会影响正常程序的性能
- 不存在硬编码
缺点
- worker模式时效性差,实时层面没有同步双写和异步双写(MQ模式)时效性高
- 对mysql数据库有一定的轮训压力,改进方法常有:对数据库的表进行分表,将轮训放到压力不大的数据库上面
Binlog模式
ps: 解决硬编码,高耦合,代码植入以及时效性差的问题,可以通过监听mysql的crud的binlog日志,将读取的信息转换为MQ,MQ通过不断消费去写入到ES中
流程: 程序–>Mysql数据库<–提取Binlog日志–>Binlog同步系统–>写入MQ<–MQ消费程序–>写入到ES
优点
- 没有代码入侵,提高低耦合和代码植入的风险
- 性能高,与业务之间完全解耦,不会影响业务的正常功能
缺点
- 构建binlog系统复杂
- 引用MQ存在时效性的问题
ES常用类型
- binary类型: 二进制类型 ,值以base64字符串的形式存贮,_source默认不会存贮该类型的值,如果需要实际的存贮,请设置 store属性为true默认是false
- Bool类型: 布尔类型 ,True或False
- Keyword类型:关键字类型,该字段适合聚合和排序的使用,在es分词中当做一个整体,如果涉及term精确查询,也可以进行考虑。
- widecard类型: 适合通配符类型和正则表达式类型搜索,而text类型不支持通配符的搜索
- 数字类型:short,interger,long unsigned_long,
- Dates类型:日期类型包含Date ,Date_nanos
- alais类型:为已存在的字段定义别名,别名可用于却大多数搜索api和field capabilities
- object类型:该类型值为一个json类型
- text类型: 该类型为全文搜索类型,常与match系列进行匹配
- Arrays类型:在ES中没有专门的数组类型,所有类型字段都可以有一个或多个的值
- nested类型:子文档就存在父文档某个字段内部,适合子文档数量较少的情况
注意:
- 一个文档最多有50个nested类型的字段
- 一个文档所有nested类型的字段存储文档最大数量是10000条
#定义一个mapping
PUT _index
{
"mapping":{
"type_name":{ #_type名称
"properties": {
"binary_name":{ #设置为binary类型字段
"type":"binary",
"store": true #默认为False,如果需要在source显示 则设置为True
},
"boolean_name":{ #设置为boolean类型字段
"type": "boolean"
},
"keyword_name":{ #设置为keyword类型字段
"type":"keyword"
},
"constant_keyword_name":{
"type": "constant_keyword", #设置该类型表示所有文档该字段值都是一样的
"value":"constant"
},
"wildcard_name": {#设置为wildcard类型字段
"type": "wildcard"
},
"integer_name": {#设置为integer类型字段
"type": "integer"
},
"float_name": {#设置为float类型字段
"type": "float"
},
"date_name":{#设置为date类型字段
"type": "date",
"format":"yyyy-MM-dd HH:mm:ss"#设置指定格式化类型,如果不设置则默认类型为yyyy-MM-dd ‘T’ HH:mm:ss.SSSZ
},
"text_name":{#设置为text_name类型字段
"type":"text"
},
"nested_name":{ #设置为nested类型字段
"type": "nested",
"properties": {
"names":{
"type":"text"
},
"alias_name":{ #设置为alias类型字段别名
"type": "alias",
"path":"nested_name.names"
}
}
}
}
}
}
ES查询
ps: 在es中默认分词器规则为英文会按照空格进行切换,大写转换为小写,中文会按照单个词进行分词
Restful基础操作
ps:为了保证演示在文章中_index表示索引的名称,_type表示索引的文档类型
获取Mapping结构
ps:PUT方法有则修改,无则新增
GET _index/_type/_mapping
创建文档
ps:PUT方法有则修改,无则新增
PUT _index/_type/1
{
"name": "xw",
"age":18
}
或
POST _index/_type/1
{
"name": "xw",
"age":18
}
查询指定的索引信息
GET _index
查询指定文档的信息
GET _index/_type/1
查询指定条件(非结构化)
GET _index/_type/_search?q=name:xuw #q:代表query,name:代表文档的对应的列字段,xuw:值
查询对应索引下所有的文档数据
GET _index/_type/_search
或
GET _index/_type/_search
"query":{
"match_all":{
}
}
删除指定的文档
DELETE _index/_type/1 #删除指定索引下的文档的第一条数据
删除指定的索引
DELETE _index
修改指定的文档方式
POST _index/_type/1/_update
{
"doc":{
"name":"xw1"
}
}
ES的基础查询-match系列
match系列-match查询
ps: match为单字段查询,不能进行多字段组合查询
#结构化写法
GET _index/type_search
{
"query":{
"match":{
"name":"xw 是好人" #根据es默认分词器,则为:['xw','是','好','人'],只要匹配任何一个则会进行返回
}
}
}
或
GET _index/type_search
{
"query":{
"match":{
"name":{ #ES的Fieled值
"query":"xw ,是好人" #根据es默认分词器,则为:['xw','是','好','人']
#"operator":"or", #默认为or,所以不写,则只需要匹配任何一个即可
#"operator": "and" #要匹配所有关键词
}
}
}
}
#参数
operator: 值为and 和 or
值and:相当于要匹配所有的关键词,对分词以后类似于mysql的:(key1=value1 and key2=value and …)
值or: 只需要匹配其中一个关键词就可,对分词以后类似于mysql的:(key1=value1 or key2=value or …)
match系列->match_all查询
ps: match_all则查询全部
ps: 类似于mysql select查询不带任何的条件
#结构化用法
GET _index/_type/_search
{
"query":{
"match_all":{
}
}
}
match系列->match_phrase
ps: match_phrase为短语查询,对应的的都要进行匹配,相对于match的operator的and
ps: match_phrase 类似mysql的 like ‘%<值>%’
#结构化用法
#例如name为: Kobe Bean Bryant
GET _index/_type/_search
{
"query":{
"match_phrase":{
"name":"Kobe Bean"
}
}
}
或
GET _index/_type/_search
{
"query":{
"match_phrase":{
"name":{
"query": "Kobe Bean",
# "slop":0 #slop参数默认为0,slop参数为两组词之间的最大可移动的间隔和顺序,在搜索的时候更加灵活
}
}
}
}
#参数
slop: 表示两组词之间的最大可移动的间隔和顺序
例如slop 为1 ,表示可以支持最大的间隔和顺序,上方query的值可以为:"Kobe Bryant"进行匹配
match系列-> match_phrase_prefix
ps: match_phrase_prefix 是最左前缀匹配,类似match_phrase ,差异点是根据分词器进行前缀匹配
ps: match_phrase_prefix相当于对分词以后,然后根据类似mysql的 like ‘<值>%’ 语法
#结构化语法
GET _index/_type/_search
{
"query":{
"match_phrase_prefix":{
"name": Kobe Be", #根据分词器然后进行最左前缀匹配,如果是"name": Kobe Be" 则match_phrase_prefix可以匹配,但是在match_phracse无法匹配
#"max_expansions":5 #前缀查询对性能影响很大,所以再使用的时候会对结果集进行限制,默认不进行限制
}
}
}
#参数
max_expansions:前缀查询对性能影响很大,所以再使用的时候会对结果集进行限制,默认不进行限制
match系列->multi_match
ps: 相对于前面几种都是单字段查询,而multi_match则是多字段查询
#结构化语法
#例如name为: Kobe Bean Bryant,remark为:Kobe Bean is beast player
GET _index/_type/_search
{
"query":{
"multi_match":{
"query":"Bean",
"fields" ["name","remark"]
#"type":"" #type选项值的可以为:phrase 和 phrase_prefix
}
}
}
#参数
type查询的类型
值为phrase: 实现 match_phrase的方法
值为phrase_prefix : 实现match_phrase_prefixd的方法
ES词项查询
ps: ES此项查询可以理解为类似于mysql的运算符
query-term:精确查询
ps: term查询可以理解为mysql中的"="
#结构化语法
#name 为 xuw
GET _index/_type/_search
{
"query":{
"term":{
"name":"xuw" #类似mysql的 name="xuw"
}
}
}
或
GET _index/_type/_search
{
"query":{
"term":{
"name":{
"value":"xuw" ,#类似mysql的 name="xuw"
"boost": 1.0 #权重
}
}
}
}
query-terms:精准多项匹配
ps:与term类似,只是terms是匹配多个,相当于mysql类似的 in语法
name 为xuw
GET _index/_type/_search
{
"query":{
"terms":{
"name":["xuw","LIH"] #类似mysql的 name in ("xuw","LIH")
}
}
}
query-range: 区间匹配
age 为19
GET _index/_type/_search
{
"query":{
"range":{
"age":{ #key值如果是字符串类型则需要加.keyword 例如: "age.keyword"
"lt": 20, #小于20
"gt": 10, #大于10
#"format": "yyyy-mm-dd" #如果查询时间范围,可以指定时间格式
}
}
}
}
或
GET _index/_type/_search
{
"query":{
"range":{
"age":{ #key值如果是字符串类型则需要加.keyword 例如: "age.keyword"
"from": 10, #小于10
"to": 20, #大于20
"includeLower": true, #为true包含下界,false不包含
"includeUpper": true #为true包含上界,false不包含
}
}
}
}
query-exists 对空值进行过滤处理
ps: query-exists查询会返回字段中至少一个非空值的文档
GET _index/_type/_search
{
"query":{
"exists":{
"field":"user" # user不存在或者user为[],null [null] 则都会进行过滤处理
}
}
}
query-prefix 对前缀进行匹配
ps:查询用于某个字段中以给定的前缀开始的文档
#name 为 hello world
GET _index/_type/_search
{
"query":{
"prefix":{
"name":"hello" #类似于mysql中的:like "hello%"
}
}
}
query-wildcard 通配符匹配
ps: 类似常用sql中的模糊匹配,支持单个字符通配符和多字符通配,"?“为1个任意字符,”*"为匹配零个或多个字符
#name 为 我是王小小
GET _index/_type/_search
{
"query":{
"wildcard":{
"name":"王小?", #可以匹配王小小,如果值为 : "王?" 则无法匹配:王小小
#"name":"王*", #可以匹配:王小,也可以匹配:王小小
#"name":"*王*" #可以匹配:洲王小,也可以匹配:洲洲洲王小
}
}
}
query-regexp 正则表达式匹配
ps: regexp为正则表达式进行匹配
name 为 W000a
GET _index/_type/_search
{
"query": {
"regexp": {
"name": "W[0-9].+"
}
}
}
query-type 查询指定类型文档
ps: 查询es下指定index下的文档
GET _index/_search
{
"query": {
"type": {
"value": "doc" #doc为指定类型的文档
}
}
}
query-ids 查询具有指定id的文档
ps: 用于查询指定type下的文档,类似mysql 中指定数据库下指定id的数据
GET _index/_type/_search
{
"query": {
"ids": {
"type": "doc" #type为对应的文档名称
"value": ["1","6"] #对应文档id为 1和6的数据
}
}
}
query-fuzzy 纠错模糊查询
ps: 自动将拼写错误的搜索文本,进行纠正,纠正以后去尝试匹配索引中的数据
- 一个字符 替换 另一个字符: _f_ox → _b_ox
- 插入 一个新的字符:sic → sic_k_
- 删除 一个字符:b_l_ack → back
#设置name为 xxuw
GET _index/_type/_search
{
"query": {
"fuzzy": {
"title": "surprize", #surprize --> 拼写错误 --> surprise --> s -> z
"fuzziness" 2 #fuzziness 默认为2,设置纠错的步骤次数
}
}
track_total_hits参数
ps:如果现实需要超过1w条数据,则需要track_total_hits为true,否则不指定该参数显示为9999
如果需要显示指定的数据,那可以指定track_total_hits具体的值
GET _index/_type/_search
{
"query":{
#省略
}
"track_total_hits":true #显示超过1w条数据加上
#"track_total_hits":200 #最大只显示200条数据
#"track_total_hits":false #最大只显示9999条数据
}
query-nested查询
ps: 对子文档下的父文档进行查询匹配,,即让数组中的对象各自地进行索引。目的是对象之间彼此独立被查询出来。
设置文档下某个studens的数据为
"student":[
{
"name":"xuw",
"sex":"男",
"age":18
},
{
"name":"jon",
"sex":"男",
"age":19
}
]
GET _type/_index/_search
{
"query":{
"nested":{
"path": "student",
"query":{
"bool":{
"must":[
"term":{
"student.name":"xuw" #如果将name 的值设置为jon,则无法搜索该数据
},
"term":{
"student.age":"18"
}
]
}
}
}
}
}
adjust_pure_negative参数
ps:这东西缺省是true,所以你显式指定了true等于没写。
用在你的条件如果全是must_not的时候,它会额外添加上一个matchALL,防止没有数据返回。
如果你显式指定了是false,它就没有数据返回了。
{
"adjust_pure_negative":true,
"query":{
#省略
}
}
boost参数
ps:查询时的权重提升 是可以用来影响相关度的主要工具,任意类型的查询都能接受 boost 参数,适当的提升boost的值会提高的相关度评分 _score
ES的基础查询-bool系列
ps: bool查询可以将一些简单的查询组合在一起,使用must ,not must,should,filter选项来表示简单逻辑之间的查询,每个选项可以支持0次到多次
must: 所有的条件都要匹配文档,类似于mysql的 and 语法,可以参与评分
must_not: 与must相反,must_not下所有的条件匹配到了文档都不会返回,must_not语句不影响评分,她的语句是将不想关的文档进行排除
should: should下的过滤条件可以匹配也可以不匹配文档,相当于mysql语法的 or ,且会参与评分
filter : filter和must实际处理逻辑是一样的,区别是:filter不评分,只是做过滤和排除,与must_not相反
GET _index/_type/_search
{
"query": {
"bool" : {
"must" : { #查询一定包含匹配查询内容,并且提供得分
#查询条件 #多个条件则每个条件为一个对应key:value;例如 "must":{条件1:判断1,条件2:判断2,条件3:判断3}
},
"filter": { #查询一定包含匹配查询内容,但是不提供得分,会对查询结果进行缓存
#查询条件 #多个条件则每个条件为一个对应key:value;例如 "filter":{条件1:判断1,条件2:判断2,条件3:判断3}
},
"must_not" : { #查询一定不包含查询内容,来自于filter 上下文,所以不会由评分,但是会缓存
#查询条件 #多个条件则每个条件为一个对应key:value;例如 "must_not":{条件1:判断1,条件2:判断2,条件3:判断3}
},
"should" : { #子查询不一定包含查询内容 有一个包含即可
#查询条件 #多个条件则每个条件为一个对应key:value;例如 "should":{条件1:判断1,条件2:判断2,条件3:判断3}
},
"minimum_should_match" : 1, #最小匹配一个should条件
"boost" : 1.0
}
}
}
或
GET _index/_type/_search
{
"query": {
"bool" : {
"must" : [ #查询一定包含匹配查询内容,并且提供得分(真真为真)
#查询条件 #多个条件则每个条件为一个字典类型例如 "must":[{条件1},{条件2},{条件3}]
[,
"filter": [ #查询一定包含匹配查询内容,但是不提供得分,会对查询结果进行缓存(真真为真)
#查询条件 #多个条件则每个条件为一个字典类型例如 "filter":[{条件1},{条件2},{条件3}]
],
"must_not" : [#查询一定不包含查询内容,来自于filter 上下文,所以不会由评分,但是会缓存(假假为真)
#查询条件 #多个条件则每个条件为一个字典类型例如 "must_not":[{条件1},{条件2},{条件3}]
],
"should" : [#子查询不一定包含查询内容 有一个包含即可(真假为真)
#查询条件 #多个条件则每个条件为一个字典类型例如 "should":[{条件1},{条件2},{条件3}]
],
"minimum_should_match" : 1, #最小匹配一个should条件
"boost" : 1.0
}
}
}
ES的排序基础操作-sort
ps: sort代表es的排序关键词,类似于mysql中的order by
#结构化语法
GET _index/_type/_search
{
"query":{
#忽略条件
}
"sort":{
"age":{
"order":"asc" #asc代表升序,desc代表降序
},
"name":{
"order":"desc" #asc代表升序,desc代表降序
}
}
}
或
GET _index/_type/_search
{
"query":{
#忽略条件
}
"sort":[
{
"age":{
"order":"asc" #asc代表升序,desc代表降序
}
},
{
"name":{
"order":"desc" #asc代表升序,desc代表降序
}
}
]
}
#上述语法类似mysql中的: order by age asc,name desc
ES的分页基础操作
ps: ES的分页是根据关键字from:从那里开始查,size:往后返回第几条数据,类似于mysql中的:LIMIT [offset,] rows
GET _index/_type/_search
{
"query":{
#忽略条件
},
"sort":{
#忽略条件
}
"from": 0, #相当于mysql的limit 的 offset,从那里开始查
"size":10 #相当于mysql的 limit 的 rows,往后返回第几条
}
#上述语法匹配mysql 的 limit 0,10
ES指定返回的字段:_source
ps: 在查询过程中,为了保证输出字段的可控,来减少资源消耗,可以使用_source来进行指定和不指定对应的字段
GET _index/_type/_search
{
"query":{
#忽略条件
},
"sort":{
#忽略条件
}
"from": 0,
"size":10,
"_source":["name","age","sex"] #指定列表中的字段作为返回,相当于 select name ,age,sex from table
}
或
GET _index/_type/_search
{
"query":{
#忽略条件
},
"sort":{
#忽略条件
}
"from": 0,
"size":10,
"_source":{
"excludes":["sex"], #不指定列表的的字段值
"includes":["name","age"] #指定列表的字段值
}
}
ES聚合
#待补充
ES和Mysql的比较
1.Mysql是关系型数据库,更擅长事务型和业务型的操作(增删改查),可以确保数据的安全和一致性。
ps:像我们正常业务中商品,客户等基础数据以及下单,支付等业务数据的场景使用
2.ES更擅长海量的数据检索,搜索,分析和计算。
ES常见的使用场景
- 打分制的搜索
- 运维平台的资源监控
- 海量数据的快速检索,分析及报表查询
- 非结构化的数据查询
- logstash日志的采集,日志的分析,复杂的数据分析
涉及ES的测试模式建立
- 需要了解业务报表相关的统计逻辑
- 根据开发给出的不同同步方式,设计不同的数据同步测试点
- 数据需要涉及增删改查(CRUD)
- 了解相关的ES相关增删改查语句,能够快速验证问题,在开发过程中发现问题和缺陷定位问题
- 了解ES相关特性例如匹配的方式,ES分词的特性等
ps:本文章参考网上相关资料,主要用于学习,如果侵权请联系我用于删除
更多推荐
所有评论(0)