ElasticSearch8 - 基本操作
前言
本文记录 ES 的一些基本操作,就是对官方文档的一些整理,按自己的习惯重新排版,凑合着看。官方的更详细,建议看官方的。
下文以 books 为索引名举例。
新增
添加单个文档 (没有索引会自动创建)
POST books/_doc
{"name": "Snow Crash", "author": "Neal Stephenson", "release_date": "1992-06-01", "age": 18}
不指定 id,会随机生成,如果需要指定 id,使用 POST books/_doc/id
还可以使用 put 的方式新增,例入 POST books/_doc/id
,这种方式必须带 id,否则会报错
以上两种方式,如果带上了 id,就是不存在就插入,存在旧更新
更新
总结 (有三种方式):
- POST 更新
- 如果 URL 带
_update
,更新前会对比新旧数据,如果新旧数据完全相同,将不会进行任何操作 noop,不会影响序列号、版本号信息。 - 如果 URI 不带
_update
,不会检查原数据,都会显示 updated
- 如果 URL 带
- PUT 更新
- 路径没法带
_update
,每次都会更新显示 updated
- 路径没法带
例如有原数据
{
"name": "zhangsan",
"age": 18
}
POST 访问:(路径带_update)
需要在参数外套一层 doc
,这种方式不影响其他字段
POST /books/_update/1
{
"doc": {
"name": "lisi"
}
}
// 执行之后原数据变成
{
"name": "lisi",
"age": 18
}
POST 访问:(路径不带_update)
和带 id 新增的语法是一样的,不存在就是插入,存在就是更新。这种方式会清空其他字段
POST /books/_doc/1
{
"name": "lisi"
}
// 执行之后原数据变成
{
"name": "lisi"
}
PUT 访问:(路径不能带_update)
效果同第 2 点
PUT /books/_doc/1
{
"name": "lisi"
}
删除
DELETE /books/_doc/1
POST /books/_delete_by_query
{查询条件...}
搜索
官方实例数据:account. json
使用 [Bulk API](Bulk API | Elasticsearch Guide [8.12] | Elastic) 来批量插入,没有安装 kibana 也可以用 postman 导入
如果插入记录搜索不到,可能是索引未来得及刷新,可以手动触发
POST /article/_refresh
根据 id 获取文档
// 获取带元数据的
GET /bank/_doc/1
// 获取不带元数据的
GET /bank/_source/1
// 判断文档是否存在
HEAD /bank/_doc/1
使用 HEAD 只会返回 {} 空对象,可以根据请求是否 404 判断文档是否存在
_search
命令搜索
注意:如果你用 es-client 连接的 es,请将 GET 换成 POST,否则查询无效
原因是 GET 请求没有带上 body 参数
默认只会返回最先匹配到的 10 条文档
GET /bank/_search
返回结果:
took
:检索花费时间,单位毫秒(从节点收到查询到将数据返回客户端之前)
timed_out
: 布尔类型,检索是否超时
hits
: 命中的记录
total.value
: 总记录的数量
hits.total
: 所有命中的记录
搜索全部
GET /bank/_search
{
"query": {
"match_all": {}
}
}
排序
Sort search results | Elasticsearch Guide [8.12] | Elastic
GET /bank/_search
{
"sort": [
{
"account_number": "desc"
},
{
"balance": { // 两种写法都行
"order": "asc"
}
}
]
}
sort
:排序条件,先对 account_number 降序,如果 account_number 相同,再对 balance 升序
其他排序参数
GET /bank/_search
{
"sort": [
{
"arr": {
"order": "desc", // 排序
"mode": "min", // 排序模式
"missing": "_last" // 缺失值处理
}
}
]
}
排序模式
用于对数组或多值字段排序。比如有数据如下
{
"age": 25,
"arr": [
11000,
23234
]
}
arr 字段就是多值字段。
升序排序的默认排序模式是 min
。默认的降序排序模式是 max
mode | 说明 |
---|---|
min | 选择最低值 |
max | 选择最高值 |
sum | 总和作为排序值 |
avg | 平均值作为排序值 |
median | 中位数作为排序值 |
缺失值处理
顾名思义,就是排序时,没有该字段的文档排前面还是排后面。
missing
值可以设置为 _last
、 _first
,默认为 _last
分页
Paginate search results | Elasticsearch Guide [8.12] | Elastic
查询方式 | 数据量 | 实时查询 | 排序 | 跳页 | 适用场景 |
---|---|---|---|---|---|
form+size 浅分页 | 小 | 支持 | 支持 | 支持 | 实时查询,跳页查询 |
scroll 标准方式 | 大 | 不支持 | 支持 | 不支持 | 深度分页,有序的批量查询 |
scroll_scan 滚动扫描 | 大 | 不支持 | 不支持 | 不支持 | 深度分页,无需的批量查询 |
search_after 分页 | 大 | 支持 | 支持 | 不支持 | 深度分页,数据批量导出 |
from + size
默认返回前 10 个结果。可以使用 from 和 size 参数,from 定义要跳过的命中数,默认 0,size 是返回的最大命中数。类比 mysql 中的 limit 0,10
默认情况下,无法使用 from
和 size
来翻阅超过 10,000 个匹配项。也就是前 10000 条数据可以用这种方式分页。如果数据太多,请使用search_after
GET /bank/_search
{
"from": 0,
"size": 10
}
search_after
注意:搜索必须指定排序字段,否则获取不到 search_after 需要的参数。
使用步骤:
一、第一页不需要使用 search_after
// 查询
GET /bank/_search
{
"sort": [ // 必须指定排序字段
"account_number",
"age"
]
}
// 响应
{
...
"hits": {
...
"hits": [
{
...
"sort": [ 0, 29]
}
]
}
}
第二页的搜索,就带上前一页的 hits.sort 中的参数
GET /bank/_search
{
"search_after": [0, 29],
"sort": [ // 必须指定排序字段
"account_number",
"age"
]
}
TODO PIT
A 查询数据,B 同时在插入数据,为了解决 A 两次查询的数据不一致,可以使用 point int time
检索选定的字段
Retrieve selected fields from a search | Elasticsearch Guide [8.12] | Elastic
关键词 fields,可以指定返回字段和格式
搜索 API
Query DSL | Elasticsearch Guide [8.12] | Elastic
Search API | Elasticsearch Guide [8.12] | Elastic
query 和 filter
query 就是普通的查询,会计算分数。
filter 不会计算分数,es 还会自动缓存常用的过滤器提高性能
说明:Query and filter context | Elasticsearch Guide [8.12] | Elastic
用法:Boolean query | Elasticsearch Guide [8.12] | Elastic
复合查询
Compound queries | Elasticsearch Guide [8.12] | Elastic
全文查询
intervals 文本灵活查询
Intervals query | Elasticsearch Guide [8.12] | Elastic
允许用户精确控制查询词在文档中出现的先后关系,实现了对 terms 顺序、terms 之间的距离以及它们之间的包含关系的灵活控制
match 模糊查询
Match query | Elasticsearch Guide [8.12] | Elastic
对基本类型,是精确匹配(比如 long、日期等)。对字符串是模糊查询,对查询的值分词,对分词的结果一一进入倒排索引去匹配
GET /ft/_search
{
"query": {
"match" : {
"my_text":{
"query": "my when",
"operator": "or"
}
}
}
}
解释:查找 my_text 字段中包含 my 或者 when 的文档。
query: 需要查询的内容
operator:默认是 or,如果改成 and,就需要 my_text 中同时包含 when 和 my
analyzer:分词器,默认使用字段的分词器
prefix 前缀查询
GET /ft/_search
{
"query": {
"prefix": {
"my_text": {
"value": "favo"
}
}
}
}
匹配 my_text 中以 favo 开头的,注意是不能分词的,也就是 my fa
查不到 cold my favourite food
,但是用 favo
可以找到
match_bool_prefix 分词前缀查询
prefix
不能分词,那么 match_bool_prefix
就来了
GET /ft/_search
{
"query": {
"match_bool_prefix": {
"my_text": {
"query": "quick brown f"
}
}
}
}
解释:先分词,最后一个词按前缀处理,前面的词语直接匹配,只要有一个命中就可以
匹配 quick brown fox
和 two quick brown ferrets
和 the fox is quick and brown
match_phrase 短语匹配查询
顾名思义,match 会分词,match_phrase 不会分词
GET /ft/_search
{
"query": {
"match_phrase": {
"my_text": {
"query": "wo shi"
}
}
}
}
match_phrase_prefix 短语前缀匹配查询
GET /ft/_search
{
"query": {
"match_phrase_prefix": {
"my_text": {
"query": "quick brown f"
}
}
}
}
与 match_bool_prefix 的区别就是不分词,匹配 quick brown fox
和two quick brown ferrets
,不匹配 the fox is quick and brown
combined_fields 组合多字段查询
Combined fields | Elasticsearch Guide [8.12] | Elastic
这个有点不太理解。
GET /ft/_search
{
"query": {
"combined_fields": {
"query": "ren shui",
"fields": [
"title",
"my_text"
],
"operator": "and"
}
}
}
解释:效果类似于将 title 和 my_text 两个字段合并成一个,再执行查询
注意,我把 operator 改成 and 了,但是只要 title 和 my_text 组合起来,包含了 ren 和 shui 就能命中
multi_match 多字段查询
Multi-match query | Elasticsearch Guide [8.12] | Elastic
在 match 查询的基础上,允许多字段查询
GET /ft/_search
{
"query": {
"multi_match": {
"query": "ren shui",
"fields": [
"title",
"my_text"
],
"operator": "and"
}
}
}
解释:我把 operator 改成了 and,那么需要 title 同时包含 ren 和 shui 两个词,或者 my_text 同时包含两个词,才能命中。和 combined_fields 有区别的。
总结
没啥好总结的,吐槽一句,官方文档对新手不太友好。新手需要的是快速使用,怎么调 api
参考
【ElasticSearch(四)】PUT&POST更新数据、DELETE删除数据、_bulk批量操作 - musecho - 博客园 (cnblogs.com)