最近实习,项目用的elasticseatch做的存储库,但是之前对于es接触的不多,查询语法有些不熟,每次想写个DSL查询时都要gpt或者施展搜索大法,所以索性就自己总结总结,以后忘了也方便查。所以这篇文章会持续更新。
数据类型
按照是否支持分词分为两大类:支持分词的数据类型,如text,match_only_text等,不支持的分词的数据类型,如keyword,date,数值型。也可以分为基本数据类型和复杂数据类型。
基本数据类型
数字类型
类型 | 说明 |
---|---|
byte | |
integer | |
short | |
long | |
double | |
float | |
half_float | 半精度16位浮点数 |
scaled_float | 缩放类型浮点数,按固定doble比例因为缩放 |
unsigned_long | 无符号64位整形 |
binary:编码为base64字符串的二进制值
boolean:布尔类型
alias:字段别名
keywords:包括keyword,constant_keyword和wildcard
dates:包括date,date_nanos
date的格式有yyyy-MM-dd HH:mm:ss、yyyy-MM-dd、时间戳
对象关系类型(复杂类型)
- object:非基本数据类型,默认的json对象为object
- flattened:单映射对象类型,其值为json
- nested:嵌套数据类型
- join:父子级关系类型
结构化类型
Range,IP,version,number3
聚合数据类型
aggregate_metric_double,histogram
文本搜索字段
text,completion,
es默认情况下会为text类型创建倒排索引
文档排名类型
空间数据类型
geo_point
其它数据类型
映射参数
analyzer:指定分词器,只有text类型字段才支持
coerce:是否支持强制类型转换
常用DSL总结
索引
-
索引名和字段名命名规范:1.英文全小写 2.不要使用驼峰3.多个单词之间用_分隔
-
索引的不可变性:索引创建成功后,索引名称、主分片数量(但可以修改副本数量)、字段类型不可变。
也不可以删除某个字段,但可以新增字段。
查询索引
es8和es6相同
GET /索引名
或
GET /索引名/_mapping
删除索引
es8和es6相同
DELETE 索引名
创建索引
es8
PUT /索引名
{
"settings":{
},
"mappings": {
"properties": {
"field1": {
"type": "text"
},
"field2": {
"type": "keyword"
}
}
}
}
es8中默认一个索引中只有_doc一种type,创建索引时不用指定type,指定type会报错,指定_doc也不行
es6
PUT /索引名
{
"settings":{
"number_of_shards": 1,
"number_of_replicas": 1
},
"mappings": {
"类型名":{
"properties": {
"新字段": {
"type": "字段类型"
}
}
}
}
}
es6中创建索引必须指定类型,不然会报错
修改索引
一个索引一旦创建后不可以删除字段、修改字段数据类型。但可以修改字段的其他属性,如fielddata等
添加新字段
es6
PUT 索引名/_mapping/类型名
{
"properties":{
"新字段名":{
"type":"新字段类型"
}
}
}
es8
PUT 索引名/_mapping
{
"properties":{
"新字段名":{
"type":"新字段类型"
}
}
}
修改settings
可以通过settings api修改某些settings,比如副本数量、index_refresh_interval、index_max_result_windows
PUT 索引名/_settings
{
"number_of_replicas":3
}
reindex
reindex不是重建索引,而是将一个索引中的数据重建到另一个索引中
POST _reindex
{
"source":{
"index":"源索引名"
},
"dest":{
"index":"目标索引名"
}
}
文档
新增文档
手动指定id,使用PUT
新增文档时可选op_type参数,该参数有create、index两个值。create:不存在则创建,存在则报错。index:不存在则创建,存在则覆盖
# 也可写为 /索引名/_create/文档id
PUT /索引名/_doc/文档id/?op_type=create
{
"字段名":"字段值",
"字段名":"字段值"
}
# 不可写为 /索引名/_index/文档id
PUT /索引名/_doc/文档id/?op_type=index
{
"字段名":"字段值",
"字段名":"字段值"
}
使用index时,如果id为某个值的文档已经存在,则会全量更新!!!
或者
PUT /索引名/_doc/1
{
"字段名":"字段值"
}
也是全量替换!!!
自动生成id,使用POST
# 也可以 /索引名/_doc/id 指定id
POST /索引名/_doc
{
"属性名":"属性值"
}
查询文档
_source
source api控制返回哪些字段
如果设置为false,则只返回元数据
GET /索引名/_doc/文档id?_source=false #此处值默认就是true
也可以使用_source只查询source源数据,不返回元数据
GET /索引名/_source/文档id
_search
POST /goods/_search
{
"query": {
"term": {
"title": "Apple"
}
}
}
除了term精准查询,还有range、match、mulit_match
批量查询文档
GET /_mget
{
"doc":[
{
"_index":"索引名",
"_id":"文档id"
},
{
"_index":"索引名",
"_id":"文档id"
}
]
}
# 可以批量查询多个索引里的多个文档
GET /索引名/_mget
{
"ids":[
1,2
]
}
#根据id批量查询一个索引里的多个文档
修改文档
全量修改
覆盖原来的文档,其本质是根据指定id删除原来的文档,新增一个相同id的文档。如果根据id删除时,id不存在,第二步的新增也会执行,也就从修改变成了新增操作了。
PUT /{索引库名}/_doc/文档id
{
"字段1": "值1",
"字段2": "值2",
// ... 略
}
其实就是put指定id新增文档
增量修改
只修改指定id匹配的文档中的部分字段
使用_update(只能通过文档id去更新)
POST /索引名/_update/文档id
{
"doc":{
"属性名":"属性值",
"属性名":"属性值"
}
}
# 通过文档id更新
在7.x之前的版本还可以这样写
POST /索引名/_doc/文档id/_update
{
"doc":{
"属性名":"属性值"
}
}
想通过query定制查询条件来更新文档,得通过_update_by_query,而且必须通过写scripts来更新
删除文档
根据query查询条件删除
删除时并不一定每次都知道文档id,通过具体查询条件删除
POST /索引名/_delete_by_query
{
"query":{
"term":{//或match
"字段名":"字段值"
}
}
}
bulk
批量插入文档
POST /_bulk
{"action":{"_index":"索引名","_id":"文档id"}}
{"属性名":"属性值","属性名":"属性值"}
{"action":{"_index":"索引名","_id":"文档id"}}
{"属性名":"属性值","属性名":"属性值"}
# action的值可选index和create,跟前面一样
批量更新文档
POST /_bulk
{"update":{"_index":"索引名","_id":"文档id"}}
{"doc":{"属性名":"属性值","属性名":"属性值"}}
{"update":{"_index":"索引名","_id":"文档id"}}
{"doc":{"属性名":"属性值","属性名":"属性值"}}
批量删除文档
POST /_bulk
{"delete":{"_index":"goods","_id":"100"}}
{"delete":{"_index":"goods","_id":"101"}}
tips:1. 每个bulk写完后,最后要有一个换行2.bulk中的一个失败不会影响其它的
Mapping
自动映射
es运行可以不用像mysql等关系型数据库一样需要提前创建表结构,可以直接插入文档,由自动映射器自动确定类型。自动映射器推断字段类型的规则:
field type | dymaic | runtime |
---|---|---|
true|false | boolean | boolean |
小数 | float | double |
整数 | long | long |
object | object | - |
数组 | 取决于数组中第一个非空元素的类型 | 同左 |
日期格式字符串 | date | date |
数字类型字符串 | text | |
其它字符串 | text+keyword | keyword |
自动映射模版
将某一类字段自动映射成特定的数据类型
match_mapping_type
用于匹配数据类型
PUT /索引名
{
"mappings":{
"dynaic_templates":[
{
"模版名":{
"match_mapping_type":"long",
"match":"num_*", //表示字段名以num_开头
"unmatch":"*_text", //表示字段名不以_text结尾
"mapping":{
"type":"integer"
}
}
},
{
"模版名":{
"match_mapping_type":"string", //string表示文本
"mapping":{
"type":"keyword"
}
}
}
]
}
}
高阶查询
match
POST /索引名/_search
{
"query":{
"match":{
"字段名":"字段值"
}
}
}
match_all
可以认为和直接GET /索引名/_search查询没什么区别
agregations聚合分析(聚合查询)
语法:
POST product/_search
{
"size":0, //不想让结果中包含hits就size为0
"aggs":{
"查询名字":{
"聚合类型":{
"field":"字段名",
"size":10, //设置桶的个数,默认为10
"order":{
"_count":"asc" //根据每个桶的文档数量升序
}
}
}
}
}
Bucket agregations
类比理解为msyql的分组查询,一个桶就是具有相同特征的一个组
聚合类型为terms时,结果:对所有的文档的某字段值进行分组查询
除了terms,还有range、date_histogram等
text类型的字段默认不会建立正排索引,所以桶聚合查询对text类型字段不生效,只对keyword类型生效。text类型字段建立正排索引不现实,而且也没意义。(你一般会在mysql里对varchar100 的desc字段建立索引?)
想对text类型的字段bucket查询,可以设置该字段的fielddata为true,则在查询时会在内存中进行分组,数据量很多时容易导致OOM,不建议这么做。
Metrics agregations指标聚合
例如统计最大、最小,平均值、总和、value_count,聚合类型分别为max、min、avg、sum、该字段值非空的文档数量。stats为这几个全部。
POST /索引名/_search
{
"aggs":{
"聚合查询名字":{
"max":{
"field":"字段名,如price"
}
},
"聚合查询名字":{
"min":{
"field":"字段名,如price"
}
}
}
}
管道聚合
跟linux里的管道一个意思,管道聚合查询就是在一个聚合查询结果作为另一个聚合查询的输入继续聚合查询。
例如查询平均价格最低的商品类型
POST /product/_search
{
"aggs":{
"查询名字1":{
"terms":{
"field":"type" //先对商品类型桶聚合
}, //在这个的基础上继续聚合查询
"aggs":{
"查询名称2":{
"avg":{
"field":"price"
}
}
}
}, //这个整个聚合得到了各个分类的平均值
"min_bucket":{
"min_bucket":{
"buckets_path":"查询名字1>查询名字2"
}
}
}
}
在谁的基础上继续聚合查询就和谁平级
组合查询 bool query
must
must表示查询条件都要满足。即 and
GET /索引名/_search
{
"query":{
"bool":{
"must":[ //must的值是数组,数组里的每一个查询条件都要满足
{
"match":{
"字段名":"目标值"
}
},//在这继续加must的其他查询条件
{
"match_phrase":{
"字段名":"目标值"
}
}
]
}
}
}
must_not
和must相反,must_not里的所有查询条件都是要排除的数据。即 !
GET /索引名/_search
{
"query":{
"bool":{
"must_not":[ //must_not的值是数组,数组里的每一个查询条件都不满足
{
"match":{
"字段名":"目标值"
}
},//在这继续加must_not的其他查询条件
{
"match_phrase":{
"字段名":"目标值"
}
}
]
}
}
}
should
也就是 or
filter
和match一样,也是and,但是filter只是过滤掉不满足条件的文档,不参与评分计算。
并且以上查询都可以组合使用
Script
es设计了painless脚本语言,老版本中用的是Grovvy,但其安全性和性能远不及painless。但painless性能是不及DSL的
!
GET /索引名/_search
{
"query":{
"bool":{
"must_not":[ //must_not的值是数组,数组里的每一个查询条件都不满足
{
"match":{
"字段名":"目标值"
}
},//在这继续加must_not的其他查询条件
{
"match_phrase":{
"字段名":"目标值"
}
}
]
}
}
}
should
也就是 or
filter
和match一样,也是and,但是filter只是过滤掉不满足条件的文档,不参与评分计算。
并且以上查询都可以组合使用
Script
es设计了painless脚本语言,老版本中用的是Grovvy,但其安全性和性能远不及painless。但painless性能是不及DSL的