- ES学习笔记
- 目录
- ES基本介绍
- 1. 引言&简介
- 2. 倒排索引
- ES的索引基本操作
- 1. 索引结构介绍
- 1.2 类型Type
- 1.1 索引index
- 1.3 类型文档
- 1.4 Field类型
- 2. 操作ES的RESTFUL语法
- 3. 索引的操作
- 3.1 创建一个索引
- 3.2 查看索引信息
- 3.3 删除索引
- 3.4 ES中Field可以指定的类型
- 3.5 创建索引并指定结构
- 3.6 文档的操作
- ES各种基础查询
- 1. term和terms查询
- 2. match查询
- 2.1 match_all查询
- 2.2 match查询
- 2.3 布尔的match查询
- 2.4 multi_match查询
- 3. 其他查询
- 3.1 id查询
- 3.2 ids查询
- 3.3 prefix查询
- 3.4 fuzzy查询
- 3.5 wildcard查询
- 3.6 range查询
- 3.7 regxp查询
- 3.8 深分页查询
- 4. 复合查询
- 4.1 bool查询
- 4.2 boosting查询
- 5. filter查询
- 6. 高亮查询
- 7. 聚合查询
- 7.1 去重计数查询
- 7.2 范围统计
- 7.3 统计聚合查询
- 7.4 地图经纬度搜索
- 7.4.1 ES的地图检索方式
- 7.4.2 基于RESTUFL实现地图检索
2. 倒排索引1.在海量数据执行搜索功能时,如果使用MySql效率太低
2.如果将关键字输入的不准确,一样可以搜索到想到的数据
3.将搜索关键字,以红色字体展示
ES时一个使用java语言并且级域Lucene编写的搜索引擎框架,它提供了分布式的全文搜索功能,他还提供了一个统一的级域RESFUL分格的web接口,官方客户端也对多种语言都提供了相应的api
Lucene:Lucene本身就是一个搜索引擎的提层。
分布式:ES主要时为了突出他的横向扩展能力。
全文检索:将一段词语进行分词,并且将分出的单个词语统一的放到一个分词库中,在搜索时,根据关键字去分词库中检索,找到匹配内容。(倒排索引)
RSETFUL风格的web接口:操作ES很简单,只需要发送一个http请求,并且根据请求方式的不同,携带参数的同时,执行相应的功能
应用广泛:Github,WIKI,GoldMan用ES每天维护奖金10TB数据。
ES的索引基本操作 1. 索引结构介绍
- 将存放的数据,以一定的方式进行分词,并且将分词的内容存放到宇哥单独的分词库中。
- 当用户去查询数据时,会将用户查询的关键字进行分词。
- 然后去分词库中匹配内容,最终得到数据的id标识。
- 根据id标识去存放数据的位置拉去到指定的数据。、
1.2 类型Type索引类型特点 :ES会对索引进行分片,并且备份
ES服务中,可以创建多个索引。
每一个索引默认被分成5片存储
每一个分片都会存在至少一个备份分片
备份分片不会帮助检索数据,当ES检索压力特别大,备份分片才会帮助检索数据
1.3 类型文档一个索引下,可以创建多个类型。
ps:根据版本不同,类型的创建也不同
1.1 索引index
- ES5.x版本中,一个index下可以创建多个Type
- ES6.x版本中,一个index下可以创建一个Type
- ES7.x版本中,一个index下没有Type
1.4 Field类型一个类型下,可以有多个文档,这个文档就类似于MySql表中的多行数据。
2. 操作ES的RESTFUL语法一个文档中们可以包含多个属性,可以包含多个属性。类似于mysql表中一行数据存在多个列。
3. 索引的操作 3.1 创建一个索引GET请求:
http://ip:port/index 查询索引信息
http://ip:port/index/type/doc_id:查询指定的文档信息
POST请求:
http://ip:port/index/type/_search 查询,可以在请求体中添加json字符串来代表查询条件
http://ip:port/index/type/doc_id/_update 修改文档,在请求体中指定json字符串代表修改的具体信息
PUT请求:
http://ip:port/index 创建一个索引,需要在请求体中指定索引的信息,类型,结构
http://ip:port/index/type/_mappings 代表创建索引时,指定索引文档存储的属性的信息
DELETE请求:
http://ip:port/index 删除跑路
http://ip:port/index/type/doc_id 删除指定的文档
#创建一个索引
PUT /person
{
"settings":{
"number_of_shards":5,
"number_of_replicas":1
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rwG5FucO-1638260761715)(ES%E5%9F%BA%E6%9C%AC%E6%93%8D%E4%BD%9C%E7%AC%94%E8%AE%B0.assets/%E4%BC%81%E4%B8%9A%E5%BE%AE%E4%BF%A1%E6%88%AA%E5%9B%BE_16381016537465.png)]
3.2 查看索引信息GET /person3.3 删除索引
DELTE /person3.4 ES中Field可以指定的类型
3.5 创建索引并指定结构常用类型介绍
string:
- text:一把被用于全文检索,将当前field进行分词
- keyword:当前field不会被分词
数值类型
- long:
- integer:
- short:
- byte:
- double:
- float:
- half:
- half_float:精度比float小一半
- scaled_float:根据一个long和scaled来表达一个浮点型,log-345,scaled-1000->345
时间类型
- date类型:针对时间类型指定具体的格式
二进制类型:
- binary类型暂时支持base64 encode string
范围类型
- long_range: 赋值时,无需指定具体的内容,只需要存储一个范围即可,指定 gt 、get lt 、lte
- integer_range: 同上。
- double_range: 同上。
- float_range: 同上。
- date_range: 同上。
- ip_range: 同上。
经纬度类型
- geo_range:用来存储经纬度,比如我们点外卖的时候,选择离我最近。
IP类型
- ip:可以存储IPV4或者IPV6
其他参数部分如可下可以参考官网https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-types.html
字段数据类型[编辑]
每个字段都有一个字段数据类型或字段类型。此类型指示字段包含的数据类型(例如字符串或布尔值)及其预期用途。例如,您可以将字符串索引到text和keyword 字段。然而,text字段值被分析用于全文搜索,而keyword字符串则保持原样用于过滤和排序。
字段类型按系列分组。同一族中的类型支持相同的搜索功能,但可能具有不同的空间使用或性能特征。
目前,唯一类型的家庭keyword,它由以下部分组成keyword, constant_keyword和wildcard字段类型。其他类型系列只有一个字段类型。例如,boolean类型系列由一种字段类型组成:boolean。
常见类型
编码为 base64 字符串的二进制值。true和false价值观。
[关键词]
关键字家庭,其中包括keyword,constant_keyword,和wildcard。
[数字]
用于表示金额的 数字类型,例如long和double。
日期
日期类型,包括[date]和 [date_nanos]。
[alias]
为现有字段定义别名。
对象和关系类型[编辑]
[object]
一个 JSON 对象。
[flattened]
整个 JSON 对象作为单个字段值。
[nested]
一个 JSON 对象,保留其子字段之间的关系。
[join]
为同一索引中的文档定义父/子关系。
结构化数据类型[编辑]
[范围]
范围类型,例如long_range,double_range, date_range,和ip_range。
[ip]
IPv4 和 IPv6 地址。
[version]
软件版本。支持语义版本控制 优先规则。
[murmur3]
计算并存储值的哈希值。
聚合数据类型[编辑]
[aggregate_metric_double]
预先聚合的指标值。
[histogram]
直方图形式的预聚合数值。
文本搜索类型[编辑]
[text 领域]
文本系列,包括text和match_only_text。经过分析的非结构化文本。
[annotated-text]
包含特殊标记的文本。用于识别命名实体。
[completion]
用于自动完成建议。
[search_as_you_type]
text-like type 用于按您类型完成。
[token_count]
文本中标记的计数。
文档排序类型[编辑]
dense_vector
记录浮点值的密集向量。
sparse_vector
记录浮点值的稀疏向量。
rank_feature
记录数字特征以在查询时提高命中率。
[rank_features]
记录数字特征以在查询时提高命中率。
空间数据类型[编辑]
geo_point
纬度和经度点。
geo_shape
复杂的形状,例如多边形。
point
任意笛卡尔点。
shape
任意笛卡尔几何。
其他类型[编辑]
percolator
以Query DSL编写的索引查询。
#创建所索引,指定数据结构
PUT /book #索引名称
{
"settings":{
"number_of_shards":5, #分片数
"number_of_replices":1 #备份数
},
"mappings":{
#类型type
"novel":{
#文档存储的类型field
"properties":{
#field属性名
"name":{
"type":"text",
#指定分词器
"analyzer":"ik_max_word",
#指定当前Field可以被作为查询条件
"index":true,
#是否需要额外存储
"store":false,
},
"auther":{
"type":"keyword"
},
"count":{
"type":"long"
},
"on-sale":{
"type":"date",
#时间类型项
"format":"yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
},
"descr":{
"type":"text",
"analyzer":"ik_max_word"
}
}
}
}
}
3.6 文档的操作
文档在ES服务中的唯一标识,’__index’,’__type ,id 三个内容为符合,锁定一个文档,操作时添加还是删除,还是修改
#自动生成文档id
POST /book/novel
{
"name": "盘龙",
"author":"我吃西红柿",
"on-sale":"2021-11-28",
"descr":"daskhjdlajskldj"
}
#手动指定id
POST /book/novel/1
{
"name": "盘龙",
"author":"我吃西红柿",
"on-sale":"2021-11-28",
"descr":"daskhjdlajskldj"
}
#修改文档,基于doc的方式
POST /book/novel/1/_update
{
"doc": {
#指定需要修改的field和对应的值
count:"123456"
}
}
#删除文档
DELETE /book/novel/1
ES各种基础查询
测试数据准备
索引:sms-logs-index
类型:sms-logs-type
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0GMoyxsN-1638260761717)(…/…/ADMINI~1/AppData/Local/Temp/%E4%BC%81%E4%B8%9A%E5%BE%AE%E4%BF%A1%E6%88%AA%E5%9B%BE_1638106230716.png)]
1. term和terms查询term的查询代表是完全匹配查询,搜索之前不会对你搜索的关键字进行分词,对你的关键字去文档分词库中去匹配内容
POST /索引/_search
{
"form":0,
"size":5,
"query":{
"term":{
"province":{
"value":"北京"
}
}
}
}
- term的查询代表是完全匹配查询,搜索之前不会对你搜索的关键字进行分词,直接去分词路中匹配,找到相应文档内容。
- terms是在针对一个字段包含多个值的时候使用,类似于mysql的in
POST /索引/_search
{
"form":0,
"size":5,
"query":{
"term":{
"province":{
"北京",
"上海",
"深圳"
}
}
}
}
2. match查询
2.1 match_all查询macth查询属于高层查询,会根据你查询的字段类型不一样,采用不同的查询方式。
match查询,实际底层是多个term查询,将term,查询的结果给你封装到了一起。
- 查询的是日期或者是数值的话,会将你基于的字符串查询内容转换为日期或者数值对待
- 如果查询的内容是一个不能被分词的内容(keyword),match查询不会对你指定的关键字分词。
- 如果查询的内容是一个可以被分词的内容(text),match会将你指定的查询的内容去分词,去分词库中匹配指定的内容。
查询全部内容,不指定任何查询条件。
POST /索引/_search
{
"query":{
"match_all":{
}
}
}
2.2 match查询
会进行分词查询,分成收货,安装,收等查询
POST /索引/_search
{
"query":{
"match":{
"smsContent":"收货安装"
}
}
}
2.3 布尔的match查询
#查询字段smsContent中既包括中国又包括健康的数据,Es默认取10条
POST /索引/_search
{
"query":{
"match":{
"smsContent":{
"query":"中国 健康",
"operator":"and" #这边还可以写 or
}
}
}
}
2.4 multi_match查询
match针对一个field做检索,multi_match针对多个field进行检索,多个field对应一个text。
#搜索这个关键字在指定字段列表中存在的数据
POST /索引/_search
{
"query":{
"multi_match":{
"query":"北京",
"fields":["province","smsContent"]
}
}
}
3. 其他查询
3.1 id查询
GET /sms-logs-index/sms-logs-type/1 #查询索引中id=1的数据3.2 ids查询
根据多个id查询,类似mysql中的where id in (id1,id2,id3…)
POST /索引/_search
{
"query":{
"ids":{
"values":["1","2","3"]
}
}
}
3.3 prefix查询
前缀查询,可以通过一个关键字去指定一个filed的前缀,从而查询到指定的文档
#搜索指定字段中,包含前缀为途虎的数据,即like "途虎%"
POST /索引/_search
{
"query":{
"prefix":{
"cropNmae":{
"value":"途虎"
}
}
}
}
3.4 fuzzy查询
模糊查询,我们输入字符的大概,ES就可以根据输入的内容大概去查询一下数据结果
#搜索指定字段中,大概模糊查询盒马鲜生->盒马先生
POST /索引/_search
{
"query":{
"fuzzy":{
"cropNmae":{
"value":"盒马先生",
"prefix_length":3 #指定数值中前多少个字符是必须一摸一样的
}
}
}
}
3.5 wildcard查询
通配查询,和mysql中的like
#搜索指定字段中类中国开头的数据类似 like "中国%"
POST /索引/_search
{
"query":{
"wildcard":{
"cropNmae":{
"value":"中国*",
}
}
}
}
#搜索指定字段中类中国开头的只有4个字的数据
POST /索引/_search
{
"query":{
"wildcard":{
"cropNmae":{
"value":"中国??",
}
}
}
}
3.6 range查询
范围查询,只针对数值类型,对某一个字段进行大于或者小于的范围指定
#搜索指定字段值大于=5小于等于10的数据#gt 大于 gte 大于等于 lt:小于 lte:小于等于
POST /索引/_search
{
"query":{
"range":{
"fee":{
"gte":5,
"lte":10
}
}
}
}
3.7 regxp查询
正则查询,通过你编写的正则表达式去匹配内容
PS:preflx,wildcard和regexp查询效率相对比较低
#搜索指定字段为180开头,后八位为数字0-9的电话号码
POST /索引/_search
{
"query":{
"regexp":{
"mobile":"180[0-9]{8}"
}
}
}
3.8 深分页查询
ES对from+size是有限制的,from和size二者之和不能超过1w
原理:
ES查询数据的方式:
第一步现将用户指定的关键进行分词。
第二步将词汇去分词库中检索,得到多个文档id。
第三步中去各个分片中去拉去指定的数据。
第四步将数据根据score进行排序。
第五步根据from的值,将查询到数据舍弃一部分。
第六步返回结果、
srcollz在ES中查询数据的方式:
第一步先将用户指定的关键字进行分词。
第二步将词汇分词库中进行检索,得到多个文档id。
第三步将文档的id存放在一个ES的上下文中
第四步根据你指定的size去ES中指定的数据,拿完数据的文档id,会从上下文中移除
第五步如果需要下一页数据,直接去ES的上下文中,找后续内容
第六步循环第四步和第五步
#scorll
POST /索引/_search?scroll_id=1m
{
"query":{
"match_all":{}
},
size:2,
"sort":[
{
"fee":{
"order":"desc"
}
}
]
}
#根据scroll查询第二页数据
POST /索引/_search
{
"scroll_id":"111111111111dsadasdasdasdasd",#从from,size查询结果中拿去的scroll_id
"scroll":"1m",#指定scroll的缓存时间
}
#删除scroll在ES上下文的数据
DELETe
/_search/scroll/{scroll_id}
4. 复合查询
4.1 bool查询
复合过滤器,将你的多个查询条件,以一定的逻辑组和在一起
- must :所有条件,用must组和在一起,表示and的意思
- must_not:将must_out中的条件,全部都不能匹配,标识not的意思
- should:所有的条件,用should组在一起表示or的意思
#查询省份为武汉或者北京
#运营商不是联通
#smsContent中包含中国和平安
#bool查询
POST /索引/_search
{
"query":{
"bool":{
"should":[
{
"term":{
"province":{
"value":"北京"
}
}
},
{
"term":{
"province":{
"value":"武汉"
}
}
}
],
"must_not":[
"term":{
"opertorId":{
"value":"2"
}
}
],
"must":[
{
"match":{
"smsContent":"中国"
}
},{
"match":{
"smsContent":"平安"
}
}
]
}
}
}
4.2 boosting查询
boosting查询可以帮助我们去影响查询后的score
positive :只有匹配上positive的查询内容,才会被放到返回的结果集中
negative:如果匹配上的positive并且也匹配上了negative,就可以降低这样的文档score。
negative_boost:指定系数,必须小于1.0
关于查询时,分数是如何计算的:
- 搜索的关键字在文档中出现的频次越高,分数就越高
- 指定的文档内容越短,分数就越高
- 我们在搜索时,指定的关键字也会被分词,这个被分词的内容,被分词库匹配的个数越多,分数越高
#boosting查询 收货安装,指定某字段中包含王五,所有的系数乘0.5降低系数
POST /索引/_search
{
"query":{
"postitive":{#查询你匹配你的结果集
"match":{
"smsContent":"收货安装"
}.
"negative":{
“match”:{
"smsContent":"王五"
}
},
"negative_boost":0.5
}
}
}
5. filter查询
- query:根据你的查询条件,去计算文档的匹配度得到一个分数,并且根据分数进行排序,不会做缓存
- filter:根据你的查询条件去查询文档,不去计算分数,而且filter会对经常被过滤的数据进行缓存。
#filter查询
POST /索引名称/_search
{
"query":{
"bool":{
"filter":[
{
"term":{
"corpName":"盒马生鲜"
}
},
"range":{
"fee":{
"lte":5
}
}
]
}
}
}
6. 高亮查询
高亮查询局势你用户输入的关键字,以一定的特殊样式显示用户,让用户知道为什么这个结果被检索出 。
高亮展示的数据,本身就是文档中的一个field,单独将field高亮的形式返回给你 。
ES提供了一个highlight属性,和query同级别的。
- fragment_size:指定高亮数据展示多少字符回来
- pre_tags:指定前缀标签,举个列子
- post_tages:指定后缀标签,举个例子
- fileds:指定那个field以高亮形式展示
#高亮查询
POST /索引名称/_search
{
"query":{
"match":{
"smsContent":"盒马"
}
},
"highlight":{
"fields":{
"smsContent":{}
}
},
"pre_tags":"",
"post_tags":"",
"fragment_size":10
}
7. 聚合查询
ES的聚合查询和mysql的聚合查询类型,es的聚合查询相比mysql要强大的多,ES提供的统计数据的方式多种多样
#ES聚合查询的RESTFUL语法
POST /index/type/_search
{
"ages":{
"名字(agg)":{#这个是给你的聚合查询起一个名字
"agg_type":{#
"属性":"值"
}
}
}
}
7.1 去重计数查询
去重计数,即Cardinality,第一步先将返回文档中的一个指定的field进行去重,统计一共有多少条,类似 MySql中的groupBy,count(),或者distance
#去重计数 查询 指定省份 每个有几个 北京 上海 武汉 山西
POST /索引/_search
{
"aggs":{
"agg":{
"cardinality":{
"field":"province"
}
}
}
}
7.2 范围统计
统计一定范围内出现的文档个数,比如针对某一个字段Field的值在0-100,100-200,200-300分别出现是多少。
范围统计可以针对普通的数值,针对时间类型,针对ip类型都可以做相应的统计。
range 、date_range、ip_range
#数值方式的统计,
POST /索引/_search
{
"aggs":{
"agg":{
"range"
"field":"fee",
"ranges":[
{
"to":5,
},
{
"from":5,#form有包含当前值的意思,to没有
"to":10
},{
"from":10
}
]
}
}
}
#时间统计
POST /索引/_search
{
"aggs":{
"date_range":{
"field":"createData",
"format":"yyyy",
"ranges":[
{
"to":2000
},
{
"from":2000
}
]
}
}
}
#ip方式的统计
POST /索引/_search
{
"aggs":{
"ip_range":{
"field":"ipAddr",
"ranges":[
{
"to":"10.126.2.9"
},{
"from":"10.126.2.9"
}
]
}
}
}
7.3 统计聚合查询
他可以帮你查询指定field的最大值,最小值、平均值、平方和、、、
使用:extended_stats
POST /索引/_search
{
"aggs":{
"agg":{
"extended_stats":{
"field":"fee"
}
}
}
}
7.4 地图经纬度搜索
ES提供了一个数据类型geo_point,这个类型就是用来存储经纬度的
创建一个带geo_point类型的索引,并添加测试数据
#创建索引 指定一个name,location经纬度地址
PUT /map{
"settings":{
"number_of_shards":5,
"number_of_replicas":1
},
"mappings":{
"map":{
"properties":{
"name":{
"type":"text"
},
"location":{
"type":"geo_point"
}
}
}
}
}
#添加索引
PUT /map/map/1
{
"name":"天安门",
"location":{
"lon":116.403681,
"lat":39.914492
}
}
7.4.1 ES的地图检索方式
7.4.2 基于RESTUFL实现地图检索geo_distance:直线距离检索方式
geo_bounding_box: 以2个点确定一个矩形,获取在矩形内的全部数据
geo_polygon:以多个点确定一个多边形,获取在多边形内的全部数据
get_distance查询
#geo_distance的查询方式
POST /map/map/_search
{
"query":{
"geo_distance":{
"location":{ #确定一个点
"lon":116.433733,
"lat":39.908404,
}
"distance":3000, #确定半径
"distance_type":"arc" #指定形状为圆形
}
}
}
geo_bounding_box 2个点确定矩形数据
POST /map/map/_search
{
"query":{
"geo_bounding_box":{
"location":{
"top_left":{ #左上角点
"lon":116.433733,
"lat":39.908404,
},
"bottom_right":{#右下角点
"lon":116.433446,
"lat":39.908404,
}
}
}
}
}
geo_polygon 多边形连点搜索
POST /map/map/_search
{
"query":{
"geo_polygon":{
"location":{
"points":[
{#第一个点
"lon":116.433733,
"lat":39.908404,
},
{#第二个点
"lon":116.433446,
"lat":39.908404,
},
{ #第三个点
"lon":116.433446,
"lat":39.908404,
}
]
}
}
}
}



