Elasticsearch 的 REST APIs

摘要

返回内容格式化

  • 返回json信息格式: ?pretty 输出格式化后的json,比如:curl http://localhost:9200/_cluster/health?pretty

  • 返回行信息格式: ?v 输出内容上方会加上标题行,比如:curl http://localhost:9200/_cat/health?v

CAT APIs

  • Elasticsearch 提供了 CAT APIs,它们提供了一种简单的方式来查看集群状态和集群中的各种资源,比如索引、分片、节点等。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
GET     /_cat/health             #查看集群当前状态:红、黄、绿
GET /_cat/master #查看master节点信息
GET /_cat/nodes #查看所有节点信息
GET /_cat/plugins #查看集群各个节点上的plugin信息
GET /_cat/indices #查看集群中所有index的详细信息
GET /_cat/indices/{index} #查看集群中指定index的详细信息,index:索引名称
GET /_cat/allocation #查看单节点的shard分配整体情况
GET /_cat/shards #查看各shard的详细情况
GET /_cat/shards/{index} #查看指定分片的详细情况
GET /_cat/segments #查看各index的segment详细信息,包括segment名, 所属shard, 内存(磁盘)占用大小, 是否刷盘
GET /_cat/segments/{index} #查看指定index的segment详细信息
GET /_cat/count #查看当前集群的doc数量
GET /_cat/count/{index} #查看指定索引的doc数量
GET /_cat/recovery #查看集群内每个shard的recovery过程.调整replica。
GET /_cat/recovery/{index} #查看指定索引shard的recovery过程
GET /_cat/pending_tasks #查看当前集群的pending task
GET /_cat/aliases #查看集群中所有alias信息,路由配置等
GET /_cat/aliases/{alias} #查看指定索引的alias信息
GET /_cat/thread_pool #查看集群各节点内部不同类型的threadpool的统计信息,
GET /_cat/fielddata #查看当前集群各个节点的fielddata内存使用情况
GET /_cat/fielddata/{fields} #查看指定field的内存使用情况,里面传field属性对应的值
GET /_cat/nodeattrs #查看单节点的自定义属性
GET /_cat/repositories #输出集群中注册快照存储库
GET /_cat/templates #输出当前正在存在的模板信息

Cluster APIs

  • Elasticsearch 提供了一系列的 Cluster APIs,它们提供了管理和监控集群状态的功能

1
2
3
4
5
6
7
8
9
GET     /_cluster/health            # 获取集群的健康状态信息,包括了集群总体的状况如status、number_of_nodes等。
GET /_cluster/stats # 提供整个集群层面的统计信息,包含索引、节点和其他高级指标。
GET /_cluster/state # 显示集群元数据的状态,包括设置、块、路由表及元数据等,允许用户查看集群的当前视图。
POST /_cluster/reroute # POST请求,用于手动改变分片分配情况,可以实现如迁移分片、取消分配等操作。
GET /_cluster/nodes/hot_threads # 返回集群中各个节点“最热”的线程堆栈跟踪,默认显示前三个CPU时间最长的线程。
GET /_cluster/allocation/explain # 解释为何某个分片被如此分配,并提供如何调整的建议。
GET /_cluster/pending_tasks # 列出所有等待执行的任务列表。
GET /_cluster/settings # 查看整个集群级别的设置。
PUT /_cluster/settings # 更新整个集群级别的设置。

Index APIs

  • Elasticsearch 提供了 Index APIs,它们提供了对索引的创建、更新、查询和删除等操作。

  • 创建索引

1
2
3
4
5
# PUT /<target>
# 这里 shopping 为索引名称,但此时没有为索引设置分片策略,也没有设置字段信息
curl -X PUT -u elastic:123456 -k 'https://127.0.0.1:9200/shopping'
# 返回值
{"acknowledged":true,"shards_acknowledged":true,"index":"shopping"}
  • 创建索引并设置索引

1
2
3
4
5
6
# PUT /<target>
curl -X PUT -u elastic:123456 -k 'https://127.0.0.1:9200/shopping' \
-H 'Content-Type: application/json' \
-d '{"settings":{"number_of_shards":"1","number_of_replicas":"2"}}'
# 返回值
{"acknowledged":true,"shards_acknowledged":true,"index":"shopping"}
  • 创建并映射索引

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# PUT /<target>
# 这里设置索引分片数量为1,副本数量为2,并设置字段信息
curl -X PUT -u elastic:123456 -k 'https://127.0.0.1:9200/shopping' \
-H 'Content-Type: application/json' \
-d '{
"settings":{
"number_of_shards":"1",
"number_of_replicas":"2"
},
"mappings":{
"properties":{
"title":{
"type":"text"
},
"category":{
"type":"keyword"
},
"price":{
"type":"double"
},
"count":{
"type":"integer"
}
}
}
}'

# 参数说明
## settings: 这个参数用于配置索引的设置,包括分片数量和副本数量。
### number_of_shards: 这个参数指定了索引中分片的数量。在这个例子中,number_of_shards 设置为 1,意味着索引将只有一个主分片。
### number_of_replicas: 这个参数指定了每个主分片的副本数量。在这个例子中,number_of_replicas 设置为 2,意味着每个主分片将有两个副本。

## mappings: 这个参数用于定义索引中的字段和字段类型。
### properties: 这个参数定义了索引中的字段和字段类型。在这个例子中,有四个字段:title、category、images 和 price。
### title: 这个字段的类型是 text,表示它是一个全文检索字段。text 适合存储长文本数据,并支持全文搜索。
### category: 这个字段的类型是 keyword,表示它是一个关键字字段,不支持全文检索。keyword 适合存储不需要分词的短文本数据(如标签、类别等),并且可以用于聚合和过滤。
### price: 这个字段的类型是 double,表示它是一个数字字段。double 表示这是一个双精度浮点数字段,适合存储数值数据,如价格
### count: 这个字段的类型是 integer,表示它是一个整数字段。integer 表示这是一个整数字段,适合存储整数数据,如商品数量等。

# 返回值
{"acknowledged":true,"shards_acknowledged":true,"index":"shopping"}
  • 更新索引映射

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# PUT /<target>/_mapping
# 注意该api只能增加新的字段,不能修改已有字段,如果要修改源字段类型或者分词器类型,下文会介绍
curl -X PUT -u elastic:123456 -k 'https://127.0.0.1:9200/shopping/_mapping' \
-H 'Content-Type: application/json' \
-d '{
"properties":{
"remark":{
"type":"text",
"analyzer":"ik_max_word",
"search_analyzer":"ik_smart"
},
"address": {
"type": "text",
"analyzer": "ik_max_word",
"fields": {
"keyword": {
"type": "keyword"
}
}
},
"tags": {
"type": "keyword"
},
"created_at": {"type": "date", "format": "yyyy-MM-dd HH:mm:ss"}
}
}'
# 参数说明
# 这里为索引添加了4个字段
# remark:新增字段,类型为text,分词器为ik_max_word,搜索分词器为ik_smart
# analyzer: 索引分词器
# search_analyzer:搜索分词器
# ik_max_word:中文分词器,将句子拆分为最多词元,适合长句子
# ik_smart:中文分词器,将句子拆分为最少词元,适合短句子
# address:新增字段,类型为text,分词器为ik_max_word,搜索分词器未指定,默认与分词器同一个,这里还为address添加了keyword字段,用于存储原始数据,以支持精确搜索
# tags:新增字段,类型为keyword,不支持分词,适合存储短文本数据(如标签、类别等),并且可以用于聚合和过滤,可以存储数组
# created_at:新增字段,类型为date,格式为yyyy-MM-dd HH:mm:ss
# 返回值
{"acknowledged":true}
  • 更新索引设置

1
2
3
4
5
6
7
# PUT /<target>/_settings
# 注意这里不能更新number_of_shards
curl -X PUT -u elastic:123456 -k 'https://127.0.0.1:9200/shopping/_settings' \
-H 'Content-Type: application/json' \
-d '{"number_of_replicas":"1"}'
# 返回值
{"acknowledged":true}
  • 查看指定索引

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# GET /<target>
curl -X GET -u elastic:123456 -k 'https://127.0.0.1:9200/shopping?pretty'
# 返回值
{
"shopping" : {
"aliases" : { },
"mappings" : {
"properties" : {
"address" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword"
}
},
"analyzer" : "ik_max_word"
},
"category" : {
"type" : "keyword"
},
"count" : {
"type" : "integer"
},
"created_at" : {
"type" : "date",
"format" : "yyyy-MM-dd HH:mm:ss"
},
"price" : {
"type" : "double"
},
"remark" : {
"type" : "text",
"analyzer" : "ik_max_word",
"search_analyzer" : "ik_smart"
},
"tags" : {
"type" : "keyword"
},
"title" : {
"type" : "text"
}
}
},
"settings" : {
"index" : {
"routing" : {
"allocation" : {
"include" : {
"_tier_preference" : "data_content"
}
}
},
"number_of_shards" : "1",
"provided_name" : "shopping",
"creation_date" : "1745291743120",
"number_of_replicas" : "1",
"uuid" : "Y1IWrdlQTUm-CbbIWweSxQ",
"version" : {
"created" : "8525000"
}
}
}
}
}
  • 查看索引设置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# GET /<target>/_settings
curl -X GET -u elastic:123456 -k 'https://127.0.0.1:9200/shopping/_settings?pretty'
# 返回值
{
"shopping" : {
"mappings" : {
"properties" : {
"address" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword"
}
},
"analyzer" : "ik_max_word"
},
"category" : {
"type" : "keyword"
},
"count" : {
"type" : "integer"
},
"created_at" : {
"type" : "date",
"format" : "yyyy-MM-dd HH:mm:ss"
},
"price" : {
"type" : "double"
},
"remark" : {
"type" : "text",
"analyzer" : "ik_max_word",
"search_analyzer" : "ik_smart"
},
"tags" : {
"type" : "keyword"
},
"title" : {
"type" : "text"
}
}
}
}
}
  • 查看字段映射

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# GET /<target>/_mapping/field/<field>
# shopping 为索引名称,title 为字段名称
curl -X GET -u elastic:123456 -k 'https://127.0.0.1:9200/shopping/_mapping/field/title?pretty'
# 返回值
{
"shopping" : {
"mappings" : {
"title" : {
"full_name" : "title",
"mapping" : {
"title" : {
"type" : "text"
}
}
}
}
}
}
  • 判断索引是否存在

1
2
3
4
5
6
7
8
9
10
11
12
13
# 使用 -I 参数来发送 HEAD 请求,可以获取响应头而不必下载响应体。
# HEAD /<target>
curl -I -u elastic:123456 -k 'https://127.0.0.1:9200/shopping'
# 返回值
HTTP/1.1 200 OK
X-elastic-product: Elasticsearch
content-type: application/json
content-length: 603

# 这个命令不会返回响应体,但它的 HTTP 响应代码可以告诉你索引的存在情况:
# 200 OK 表示索引存在。
# 404 Not Found 表示索引不存在。

  • 删除索引

1
2
3
4
# DELETE /<target>
curl -X DELETE -u elastic:123456 -k 'https://127.0.0.1:9200/shopping'
# 返回值
{"acknowledged":true}
  • 为索引创建别名

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 注意:不同索引可以有相同名称的别名,所以在数据结构一致的情况下,我们可以为不同的索引创建相同的别名,然后根据别名进行数据查询
# POST /<target>/_alias/<alias>
curl -X POST -u elastic:123456 -k 'https://127.0.0.1:9200/shopping/_alias/shopping_alias'
# 返回值
{"acknowledged":true}

# 也可以使用如下方法
curl -X POST -u elastic:123456 -k 'https://127.0.0.1:9200/_aliases' \
-H 'Content-Type: application/json' \
-d '{
"actions": [
{
"add": {
"index": "shopping",
"alias": "shopping_alias2"
}
}
]
}'
# 返回值
{"acknowledged":true}
  • 查看索引别名

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# GET /<target>/_alias/<alias>
curl -X GET -u elastic:123456 -k 'https://127.0.0.1:9200/shopping/_alias/shopping_alias?pretty'
# 返回值
{
"shopping" : {
"aliases" : {
"shopping_alias" : { }
}
}
}

# 查看当前索引的所有别名
curl -X GET -u elastic:123456 -k 'https://127.0.0.1:9200/shopping/_alias?pretty'

# 查看所有索引的别名
curl -X GET -u elastic:123456 -k 'https://127.0.0.1:9200/_alias?pretty'
  • 为索引删除别名

1
2
3
4
# DELETE /<target>/_alias/<alias>
curl -X DELETE -u elastic:123456 -k 'https://127.0.0.1:9200/shopping/_alias/shopping_alias'
# 返回值
{"acknowledged":true}

如何修改索引字段类型或分词器类型?

  • 创建新的索引

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# 这里为title字段增加分词器
curl -X PUT -u elastic:123456 -k 'https://127.0.0.1:9200/shopping_new' \
-H 'Content-Type: application/json' \
-d '{
"settings":{
"number_of_shards":"1",
"number_of_replicas":"2"
},
"mappings":{
"properties":{
"category":{
"type":"keyword"
},
"price":{
"type":"double"
},
"count":{
"type":"integer"
},
"title":{
"type":"text",
"analyzer":"ik_max_word",
"search_analyzer":"ik_smart"
},
"remark":{
"type":"text",
"analyzer":"ik_max_word",
"search_analyzer":"ik_smart"
},
"address": {
"type": "text",
"analyzer": "ik_max_word",
"fields": {
"keyword": {
"type": "keyword"
}
}
},
"tags": {
"type": "keyword"
},
"created_at": {"type": "date", "format": "yyyy-MM-dd HH:mm:ss"}
}
}
}'
  • 将原索引的数据迁移到新索引

1
2
3
4
5
6
7
8
9
10
11
12
curl -X POST -u elastic:123456 -k 'https://127.0.0.1:9200/_reindex' \
-H 'Content-Type: application/json' \
-d '{
"source": {
"index": "shopping"
},
"dest": {
"index": "shopping_new"
}
}'
# 返回值
{"took":101,"timed_out":false,"total":2,"updated":0,"created":2,"deleted":0,"batches":1,"version_conflicts":0,"noops":0,"retries":{"bulk":0,"search":0},"throttled_millis":0,"requests_per_second":-1.0,"throttled_until_millis":0,"failures":[]}
  • 删除原索引

1
2
3
curl -X DELETE -u elastic:123456 -k 'https://127.0.0.1:9200/shopping'
# 返回值
{"acknowledged":true}
  • 为新索引创建别名

1
2
3
curl -X POST -u elastic:123456 -k 'https://127.0.0.1:9200/shopping_new/_alias/shopping'
# 返回值
{"acknowledged":true,"errors":false}

数据增删改基本操作

  • 新增数据

    • 1.为指定索引插入一条数据(_doc方式:不指定id默认随机字符串)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    # _doc 的方式创建索引数据时,可以不指定id,默认会创建新的id,id类型为随机字符串
    # POST /<target>/_doc
    curl -X POST -u elastic:123456 -k 'https://127.0.0.1:9200/shopping/_doc?pretty' \
    -H 'Content-Type: application/json' \
    -d '{
    "category": "electronics",
    "price": 999.99,
    "count": 10,
    "title": "Smartphone X - 128GB",
    "remark": "This latest Smartphone X comes with a powerful processor and high-resolution camera.",
    "address": "123 Electronic Ave, Beijing, China",
    "tags": ["latest", "smartphone", "technology"],
    "created_at": "2025-04-22 03:30:02"
    }'
    # 返回值
    {
    "_index" : "shopping_new",
    "_id" : "sImNW5YBmgASmV9McVvI",
    "_version" : 1,
    "result" : "created",
    "_shards" : {
    "total" : 3,
    "successful" : 1,
    "failed" : 0
    },
    "_seq_no" : 1,
    "_primary_term" : 1
    }
    • 2.为指定索引插入一条数据(_doc方式:指定id)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    # _doc 的方式创建索引数据时,如果指定id,再次执行时会先删除原数据再创建新数据,所以必须全量更新才行。
    # PUT /<target>/_doc
    curl -X PUT -u elastic:123456 -k 'https://127.0.0.1:9200/shopping/_doc/100?pretty' \
    -H 'Content-Type: application/json' \
    -d '{
    "category": "electronics",
    "price": 999.99,
    "count": 10,
    "title": "Smartphone X - 128GB",
    "remark": "This latest Smartphone X comes with a powerful processor and high-resolution camera.",
    "address": "123 Electronic Ave, Beijing, China",
    "tags": ["latest", "smartphone", "technology"],
    "created_at": "2025-04-22 03:30:02"
    }'
    # 返回值
    {
    "_index" : "shopping_new",
    "_id" : "100",
    "_version" : 1,
    "result" : "created",
    "_shards" : {
    "total" : 3,
    "successful" : 1,
    "failed" : 0
    },
    "_seq_no" : 2,
    "_primary_term" : 1
    }
    • 3.为指定索引插入一条数据(_create方式:指定id)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    # _create 的方式创建索引数据时,必须指定id,而且只能执行一次,因为执行过一次后指定id的数据就存在了,不能再次创建
    # POST /<target>/_create/<id>
    curl -X POST -u elastic:123456 -k 'https://127.0.0.1:9200/shopping/_create/1?pretty' \
    -H 'Content-Type: application/json' \
    -d '{
    "category": "electronics",
    "price": 999.99,
    "count": 10,
    "title": "Smartphone X - 128GB",
    "remark": "This latest Smartphone X comes with a powerful processor and high-resolution camera.",
    "address": "123 Electronic Ave, Beijing, China",
    "tags": ["latest", "smartphone", "technology"],
    "created_at": "2025-04-22 03:30:02"
    }'
  • 修改数据

    • 1.修改全部数据
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    # POST /<target>/_doc/<id>
    # 执行时会先删除原数据再创建新数据,所以必须全量更新才行。
    curl -X POST -u elastic:123456 -k 'https://127.0.0.1:9200/shopping/_doc/sImNW5YBmgASmV9McVvI' \
    -H 'Content-Type: application/json' \
    -d '{
    "category": "electronics",
    "price": 999.99,
    "count": 20,
    "title": "Smartphone X - 128GB",
    "remark": "This latest Smartphone X comes with a powerful processor and high-resolution camera.",
    "address": "123 Electronic Ave, Beijing, China",
    "tags": ["latest", "smartphone", "technology"],
    "created_at": "2025-04-22 03:30:02"
    }'
    • 2.修改部分数据
    1
    2
    3
    4
    5
    # POST /<target>/_update/<id>
    # 执行时只会修改指定字段,不会删除原数据,所以可以部分更新。
    curl -X POST -u elastic:123456 -k 'https://127.0.0.1:9200/shopping/_update/1' \
    -H 'Content-Type: application/json' \
    -d '{"doc":{"count":100}}'
  • 查询指定索引的指定id的数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# GET /<target>/_doc/<id>
curl -X GET -u elastic:123456 -k 'https://127.0.0.1:9200/shopping/_doc/100?pretty'
# 返回值
{
"_index" : "shopping_new",
"_id" : "100",
"_version" : 1,
"_seq_no" : 2,
"_primary_term" : 1,
"found" : true,
"_source" : {
"category" : "electronics",
"price" : 999.99,
"count" : 10,
"title" : "Smartphone X - 128GB",
"remark" : "This latest Smartphone X comes with a powerful processor and high-resolution camera.",
"address" : "123 Electronic Ave, Beijing, China",
"tags" : [
"latest",
"smartphone",
"technology"
],
"created_at" : "2025-04-22 03:30:02"
}
}
  • 删除指定索引的指定id的数据

1
2
# DELETE /<target>/_doc/<id>
curl -X DELETE -u elastic:123456 -k 'https://127.0.0.1:9200/shopping/_doc/100'
  • 删除索引全部数据

1
2
3
curl -X POST -u elastic:123456 -k 'https://127.0.0.1:9200/shopping/_delete_by_query?pretty' \
-H 'Content-Type: application/json' \
-d '{"query":{"match_all":{}}}'

批量操作

  • 批量新增数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# 注意数据行要顶行写,前面不要有空格
# POST /_bulk
curl -X POST -u elastic:123456 -k 'https://127.0.0.1:9200/_bulk' \
-H 'Content-Type: application/json' \
-d '{ "index": { "_index": "shopping", "_id": "1" } }
{ "category": "electronics", "price": 999.99, "count": 10, "title": "Smartphone X - 128GB", "remark": "This latest Smartphone X comes with a powerful processor and high-resolution camera.", "address": "广州天河公园", "tags": ["latest", "smartphone", "technology"], "created_at": "2025-04-22 03:30:02" }
{ "index": { "_index": "shopping", "_id": "2" } }
{ "category": "fashion", "price": 49.99, "count": 25, "title": "Designer T-shirt", "remark": "Trendy designer T-shirt made with high quality fabric.", "address": "广州荔湾大厦", "tags": ["clothing", "designer", "style"], "created_at": "2025-04-21 12:15:00" }
{ "index": { "_index": "shopping", "_id": "3" } }
{ "category": "home_appliances", "price": 299.99, "count": 5, "title": "Robot Vacuum Cleaner", "remark": "Efficient robot vacuum cleaner with smart navigation.", "address": "广州白云山公园", "tags": ["appliances", "vacuum", "robot"], "created_at": "2025-04-20 08:45:30" }
{ "index": { "_index": "shopping", "_id": "4" } }
{ "category": "books", "price": 19.99, "count": 100, "title": "Inspirational Novel", "remark": "A gripping novel that inspires and motivates.", "address": "321 Book Rd, Shenzhen, China", "tags": ["book", "novel", "inspiration"], "created_at": "2025-04-19 10:05:00" }
{ "index": { "_index": "shopping", "_id": "5" } }
{ "category": "groceries", "price": 3.99, "count": 200, "title": "Organic Apples", "remark": "Fresh and crispy organic apples.", "address": "654 Grocery Ln, Chengdu, China", "tags": ["fruit", "organic", "healthy"], "created_at": "2025-04-18 14:30:45" }
{ "index": { "_index": "shopping", "_id": "6" } }
{ "category": "electronics", "price": 1999.99, "count": 15, "title": "Smartphone X - 256GB", "remark": "This latest Smartphone X comes with a powerful processor and high-resolution camera.", "address": "广州天河公园", "tags": ["latest", "smartphone", "technology"], "created_at": "2025-04-22 03:30:02" }
'
# 参数说明
# index: 用于创建新文档或替换已有文档。
# create: 用于创建新文档,如果文档已存在,则返回错误。
# _index: 指定索引名称。
# _id: 指定文档ID。如果不指定则会自动生成一个随机的ID。

# 批量新增数据时也可以在url中指定索引名称
# 此时可以指定id,如果不指定则自动生成一个随机字符串的ID
# POST /<target>/_bulk
curl -X POST -u elastic:123456 -k 'https://127.0.0.1:9200/shopping/_bulk' \
-H 'Content-Type: application/json' \
-d '{ "index": {} }
{ "category": "electronics", "price": 999.99, "count": 10, "title": "Smartphone X - 128GB", "remark": "This latest Smartphone X comes with a powerful processor and high-resolution camera.", "address": "广州天河公园", "tags": ["latest", "smartphone", "technology"], "created_at": "2025-04-22 03:30:02" }
{ "index": {} }
{ "category": "fashion", "price": 49.99, "count": 25, "title": "Designer T-shirt", "remark": "Trendy designer T-shirt made with high quality fabric.", "address": "广州荔湾大厦", "tags": ["clothing", "designer", "style"], "created_at": "2025-04-21 12:15:00" }
{ "index": {} }
{ "category": "home_appliances", "price": 299.99, "count": 5, "title": "Robot Vacuum Cleaner", "remark": "Efficient robot vacuum cleaner with smart navigation.", "address": "广州白云山公园", "tags": ["appliances", "vacuum", "robot"], "created_at": "2025-04-20 08:45:30" }
{ "index": {} }
{ "category": "books", "price": 19.99, "count": 100, "title": "Inspirational Novel", "remark": "A gripping novel that inspires and motivates.", "address": "321 Book Rd, Shenzhen, China", "tags": ["book", "novel", "inspiration"], "created_at": "2025-04-19 10:05:00" }
{ "index": {} }
{ "category": "groceries", "price": 3.99, "count": 200, "title": "Organic Apples", "remark": "Fresh and crispy organic apples.", "address": "654 Grocery Ln, Chengdu, China", "tags": ["fruit", "organic", "healthy"], "created_at": "2025-04-18 14:30:45" }
{ "index": {} }
{ "category": "electronics", "price": 1999.99, "count": 15, "title": "Smartphone X - 256GB", "remark": "This latest Smartphone X comes with a powerful processor and high-resolution camera.", "address": "广州天河公园", "tags": ["latest", "smartphone", "technology"], "created_at": "2025-04-22 03:30:02" }
'
  • 批量修改数据

1
2
3
4
5
6
7
8
9
10
11
# 注意数据行要顶行写,前面不要有空格
curl -X POST -u elastic:123456 -k 'https://127.0.0.1:9200/_bulk' \
-H 'Content-Type: application/json' \
-d '{"update":{"_index":"shopping","_id":"1"}}
{"doc":{"title":"Smartphone X2 - 128GB","price":1000.11}}
{"update":{"_index":"shopping","_id":"2"}}
{"doc":{"title":"T-shirt","price":45.99}}
'
# 参数说明
# update: 用于更新文档。
# doc: 指定要更新的字段。
  • 批量删除数据

1
2
3
4
5
6
7
8
9
10
# 注意数据行要顶行写,前面不要有空格
curl -X POST -u elastic:123456 -k 'https://127.0.0.1:9200/_bulk' \
-H 'Content-Type: application/json' \
-d '{"delete":{"_index":"shopping","_id":"1"}}
{"delete":{"_index":"shopping","_id":"2"}}
{"delete":{"_index":"shopping","_id":"3"}}
{"delete":{"_index":"shopping","_id":"4"}}
'
# 参数说明
# delete: 用于删除文档。

条件更新

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# POST /<target>/_update_by_query
# 这里将category为华为的数据价格改为1999
curl -X POST -u elastic:123456 -k 'https://127.0.0.1:9200/shopping/_update_by_query?pretty' \
-H 'Content-Type: application/json' \
-d '{
"query": {
"match": {
"category": "books"
}
},
"script": {
"source": "ctx._source.price = 20.99",
"lang": "painless"
}
}'
# 参数说明
## "query": {} 查询条件
## "script": {} 脚本
### source: 脚本内容
### lang: 脚本语言
#### painless 是 Elasticsearch 官方提供的脚本语言,它提供了许多内置函数和变量,可以方便地实现各种复杂的逻辑操作。https://www.elastic.co/guide/en/elasticsearch/painless/current/painless-lang-spec.html

条件删除

1
2
3
4
# POST /<target>/_delete_by_query
curl -X POST -u elastic:123456 -k 'https://127.0.0.1:9200/shopping/_delete_by_query?pretty' \
-H 'Content-Type: application/json' \
-d '{"query":{"match":{"category":"books"}}}'

条件查询

match_all: 全部匹配查询

1
2
3
4
5
6
7
# GET /<target>/_search
curl -X GET -u elastic:123456 -k 'https://127.0.0.1:9200/shopping/_search?pretty'
-H 'Content-Type: application/json' \
-d '{"query":{"match_all":{}}}'

# 或者简写为
curl -X GET -u elastic:123456 -k 'https://127.0.0.1:9200/shopping/_search?pretty'

term: 精确匹配查询(关键字查询,即不分词)

1
2
3
4
5
6
7
8
9
10
11
12
13
curl -X GET -u elastic:123456 -k 'https://127.0.0.1:9200/shopping/_search?pretty' \
-H 'Content-Type: application/json' \
-d '{"query":{"term":{"category":"electronics"}}}'

# 如果字段被额外设置 keyword 类型,则需要加上 .keyword 后缀
curl -X GET -u elastic:123456 -k 'https://127.0.0.1:9200/shopping/_search?pretty' \
-H 'Content-Type: application/json' \
-d '{"query":{"term":{"address.keyword":"广州白云山公园"}}}'

# term处理多值字段(数组)时,term查询是包含,不是等于
curl -X GET -u elastic:123456 -k 'https://127.0.0.1:9200/shopping/_search?pretty' \
-H 'Content-Type: application/json' \
-d '{"query":{"term":{"tags":"technology"}}}'

terms: 多关键字精确匹配查询

1
2
3
curl -X GET -u elastic:123456 -k 'https://127.0.0.1:9200/shopping/_search?pretty' \
-H 'Content-Type: application/json' \
-d '{"query":{"terms":{"category":["electronics","books"]}}}'

range: 范围查询

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
curl -X GET -u elastic:123456 -k 'https://127.0.0.1:9200/shopping/_search?pretty' \
-H 'Content-Type: application/json' \
-d '{"query":{"range":{"price":{"gte":20,"lte":30}}}}'
# gte: 大于等于
# lte: 小于等于
# gt: 大于
# lt: 小于

# 时间范围查询
curl -X GET -u elastic:123456 -k 'https://127.0.0.1:9200/shopping/_search?pretty' \
-H 'Content-Type: application/json' \
-d '{"query":{"range":{"created_at":{"gte":"2025-04-20 00:00:00","lte":"2025-05-20 23:59:59"}}}}'

# 基于日期数学表达式查询
curl -X GET -u elastic:123456 -k 'https://127.0.0.1:9200/shopping/_search?pretty' \
-H 'Content-Type: application/json' \
-d '{"query":{"range":{"created_at":{"gte":"now-1y"}}}}'

# 支持的日期表达式
# - now:当前时间点。
# - now-1d:从当前时间点向前推1天的时间点。
# - now-1w:从当前时间点向前推1周的时间点。
# - now-1M:从当前时间点向前推1个月的时间点。
# - now-1y:从当前时间点向前推1年的时间点。
# - now+1h:从当前时间点向后推1小时的时间点。

exists: 查询字段存在的数据

1
2
3
4
5
curl -X GET -u elastic:123456 -k 'https://127.0.0.1:9200/shopping/_search?pretty' \
-H 'Content-Type: application/json' \
-d '{"query":{"exists":{"field":"title"}}}'
# field: 指定要查询的字段
# 示例:查询 title 字段存在的文档

ids: 根据一组ID查询

1
2
3
4
5
curl -X GET -u elastic:123456 -k 'https://127.0.0.1:9200/shopping/_search?pretty' \
-H 'Content-Type: application/json' \
-d '{"query":{"ids":{"values":["1","2"]}}}'
# values: 指定要查询的ID列表
# 示例:查询ID为1和2的文档

prefix: 前缀查询

  • 仅适用于关键字类型(keyword)的字段

1
2
3
4
5
6
7
8
9
10
11
12
curl -X GET -u elastic:123456 -k 'https://127.0.0.1:9200/shopping/_search?pretty' \
-H 'Content-Type: application/json' \
-d '{"query":{"prefix":{"category":"elec"}}}'

# 仅适用于keyword类型字段,所以下面这个请求查询不到数据
curl -X GET -u elastic:123456 -k 'https://127.0.0.1:9200/shopping/_search?pretty' \
-H 'Content-Type: application/json' \
-d '{"query":{"prefix":{"address":"广州白云山"}}}'
# 因为address被附加了keyword类型,所以需要加上.keyword后缀后可以查询到数据
curl -X GET -u elastic:123456 -k 'https://127.0.0.1:9200/shopping/_search?pretty' \
-H 'Content-Type: application/json' \
-d '{"query":{"prefix":{"address.keyword":"广州白云山"}}}'

wildcard: 通配符查询

  • 仅适用于关键字类型(keyword)的字段

1
2
3
4
5
curl -X GET -u elastic:123456 -k 'https://127.0.0.1:9200/shopping/_search?pretty' \
-H 'Content-Type: application/json' \
-d '{"query":{"wildcard":{"category":"e?e*"}}}'
# ?: 任意单个字符
# *: 任意多个字符

regexp: 正则表达式查询

  • 仅适用于关键字类型(keyword)的字段

1
2
3
curl -X GET -u elastic:123456 -k 'https://127.0.0.1:9200/shopping/_search?pretty' \
-H 'Content-Type: application/json' \
-d '{"query":{"regexp":{"category":"e.e.*"}}}'

fuzzy: 支持编辑距离的模糊查询

  • 仅适用于关键字类型(keyword)的字段

  • fuzzy检索是一种强大的搜索功能,它能够在用户输入内容存在拼写错误或上下文不一致时,仍然返回与搜索词相似的文档。通过使用编辑距离算法来度量输入词与文档中词条的相似程度,模糊查询在保证搜索结果相关性的同时,有效地提高了搜索容错能力。

  • 编辑距离是指从一个单词转换到另一个单词需要编辑单字符的次数。如中文集团到中威集团编辑距离就是1,只需要修改一个字符;如果fuzziness值在这里设置成2,会把编辑距离为2的东东集团也查出来。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
curl -X GET -u elastic:123456 -k 'https://127.0.0.1:9200/shopping/_search?pretty' \
-H 'Content-Type: application/json' \
-d '{
"query":{
"fuzzy":{
"category":{
"value":"beeks",
"fuzziness":"2",
"prefix_length":1
}
}
}
}'
# fuzziness:用于编辑距离的设置,其默认值为AUTO,支持的数值为[0,1,2]。如果值设置越界会报错。
# prefix_length: 搜索词的前缀长度,在此长度内不会应用模糊匹配。默认是0,即整个词都会被模糊匹配。

match: 全文检索(即分词)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
curl -X GET -u elastic:123456 -k 'https://127.0.0.1:9200/shopping/_search?pretty' \
-H 'Content-Type: application/json' \
-d '{"query":{"match":{"address":"广州白云山公园"}}}'

# 因为 desc 的索引分词器是 ik_max_word,查看“广州白云山公园”被分词后的结果
curl -X GET -u elastic:123456 -k 'https://127.0.0.1:9200/_analyze?pretty' \
-H 'Content-Type: application/json' \
-d '{
"analyzer": "ik_max_word",
"text": "广州白云山公园"
}'
# 返回值
{
"tokens" : [
{
"token" : "广州",
"start_offset" : 0,
"end_offset" : 2,
"type" : "CN_WORD",
"position" : 0
},
{
"token" : "白云山",
"start_offset" : 2,
"end_offset" : 5,
"type" : "CN_WORD",
"position" : 1
},
{
"token" : "白云",
"start_offset" : 2,
"end_offset" : 4,
"type" : "CN_WORD",
"position" : 2
},
{
"token" : "云山",
"start_offset" : 3,
"end_offset" : 5,
"type" : "CN_WORD",
"position" : 3
},
{
"token" : "公园",
"start_offset" : 5,
"end_offset" : 7,
"type" : "CN_WORD",
"position" : 4
}
]
}
# 所以只要desc中包含如上这些内容的数据都会被匹配上

# 但是这样匹配的结果就不够精确,如何尽量匹配更多的分词呢,可以增加 minimum_should_match
curl -X GET -u elastic:123456 -k 'https://127.0.0.1:9200/shopping/_search?pretty' \
-H 'Content-Type: application/json' \
-d '{
"query":{
"match":{
"address":{
"query": "广州白云山公园",
"minimum_should_match": 2
}
}
}
}'
# minimum_should_match: 2 表示至少匹配两个

# 如果希望全部都匹配呢
curl -X GET -u elastic:123456 -k 'https://127.0.0.1:9200/shopping/_search?pretty' \
-H 'Content-Type: application/json' \
-d '{
"query":{
"match":{
"address":{
"query": "广州白云山公园",
"operator": "and"
}
}
}
}'
# operator: and 表示全部匹配,此时相当于精确匹配,其默认值是 or

multi_match: 多字段查询

  • multi_match查询在Elasticsearch中用于在多个字段上执行相同的搜索操作。它可以接受一个查询字符串,并在指定的字段集合中搜索这个字符串。multi_match查询提供了灵活的匹配类型和操作符选项,以便根据不同的搜索需求调整搜索行为。

1
2
3
4
5
6
7
8
9
10
11
12
curl -X GET -u elastic:123456 -k 'https://127.0.0.1:9200/shopping/_search?pretty' \
-H 'Content-Type: application/json' \
-d '{
"query":{
"multi_match":{
"query": "广州shirt",
"fields":["title","address"]
}
}
}'
# query: 查询条件
# fields: 指定多个字段进行匹配

match_phrase: 短语查询

  • match_phrase查询在Elasticsearch中用于执行短语搜索,它不仅匹配整个短语,而且还考虑了短语中各个词的顺序和位置。这种查询类型对于搜索精确短语非常有用,尤其是在用户输入的查询与文档中的文本表达方式需要严格匹配时。

1
2
3
4
5
6
7
8
9
10
11
12
curl -X GET -u elastic:123456 -k 'https://127.0.0.1:9200/shopping/_search?pretty' \
-H 'Content-Type: application/json' \
-d '{
"query":{
"match_phrase":{
"address":{
"query":"广州白云山"
}
}
}
}'
# 要求查询结果中的数据必须包含"广州白云山",而且“广州”和“白云山”这两个词是不能分开的,因为 match_phrase 匹配的是相邻词条

query_string: 支持与或非表达式的查询

  • query_string查询是一种灵活的查询类型,它允许使用Lucene查询语法来构建复杂的搜索查询。这种查询类型支持多种逻辑运算符,包括与(AND)、或(OR)和非(NOT),以及通配符、模糊搜索和正则表达式等功能。query_string查询可以在单个或多个字段上进行搜索,并且可以处理复杂的查询逻辑。

  • 注意: 查询字段分词就将查询条件分词查询,查询字段不分词将查询条件不分词查询

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# 查询所有字段中包含 "公园"和 "华为" 的文档
curl -X GET -u elastic:123456 -k 'https://127.0.0.1:9200/shopping/_search?pretty' \
-H 'Content-Type: application/json' \
-d '{
"query":{
"query_string":{
"query":"公园 AND electronics"
}
}
}'

# 指定查询的单个字段
curl -X GET -u elastic:123456 -k 'https://127.0.0.1:9200/shopping/_search?pretty' \
-H 'Content-Type: application/json' \
-d '{
"query":{
"query_string":{
"default_field":"category",
"query":"白云山 OR books"
}
}
}'

# 指定查询的多个字段
curl -X GET -u elastic:123456 -k 'https://127.0.0.1:9200/shopping/_search?pretty' \
-H 'Content-Type: application/json' \
-d '{
"query":{
"query_string":{
"fields":["category","address"],
"query":"白云山 OR (electronics AND shirt)"
}
}
}'

simple_query_string: 类似 query_string,但是会忽略错误的语法,同时只支持部分查询语法

1
2
3
4
5
6
7
8
9
10
11
curl -X GET -u elastic:123456 -k 'https://127.0.0.1:9200/shopping/_search?pretty' \
-H 'Content-Type: application/json' \
-d '{
"query":{
"simple_query_string":{
"query":"广州公园",
"default_operator":"AND"
}
}
}'
# default_operator: 默认为 OR,设置为 AND 则必须同时匹配

ES查询结果属性含义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{
"took":16, # 表示查询从请求到完成耗时 16 毫秒。
"timed_out":false, # 表示查询在规定的时间内完成,没有发生超时。如果为 true,则表示查询超时。
"_shards":{ # 涉及到查询过程中使用的分片信息
"total":1, # 表示查询涉及到的总分片数为 1
"successful":1, # 表示查询成功完成的分片数为 1
"skipped":0, # 表示查询过程中被跳过的分片数为 0
"failed":0 # 表示查询过程中失败的分片数为 0
},
"hits":{ # 包含查询结果的详细信息
"total":{ # 包含查询结果的总数
"value":4, # 表示查询结果的总数为 4
"relation":"eq" # 表示返回的总数 value 是确切的(equal)。如果为 gte,则表示返回的总数是一个下限值。
},
"max_score":0.0, # 表示匹配到的文档中最高的得分。如果是排序查询,这个值会有意义。当前结果因为 size: 0,没有实际返回文档,所以得分为 0.0
"hits":[ ] # 包含查询结果的列表,每个结果都是一个对象,包含文档的元数据,如 id、分数等。
}
}

bool 查询

  • 布尔查询可以按照布尔逻辑条件组织多条查询语句,只有符合整个布尔条件的文档才会被搜索出来。

  • 在布尔条件中,可以包含两种不同的上下文。

    • 1.搜索上下文(query context):使用搜索上下文时,Elasticsearch需要计算每个文档与搜索条件的相关度得分,这个得分的计算需使用一套复杂的计算公式,有一定的性能开销,带文本分析的全文检索的查询语句很适合放在搜索上下文中。
    • 2.过滤上下文(filter context):使用过滤上下文时,Elasticsearch只需要判断搜索条件跟文档数据是否匹配,例如使用Term query判断一个值是否跟搜索内容一致,使用Range query判断某数据是否位于某个区间等。过滤上下文的查询不需要进行相关度得分计算,还可以使用缓存加快响应速度,很多术语级查询语句都适合放在过滤上下文中。
  • bool 查询包含 must、must_not、should、filter 四种子句。

类型 说明
must 可包含多个查询条件,每个条件均满足的文档才能被搜索到,每次查询需要计算相关度得分,属于搜索上下文
should 可包含多个查询条件,不存在must和fiter条件时,至少要满足多个查询条件中的一个,文档才能被搜索到,否则需满足的条件数量不受限制,匹配到的查询越多相关度越高,也属于搜索上下文
filter 可包含多个过滤条件,每个条件均满足的文档才能被搜索到,每个过滤条件不计算相关度得分,结果在一定条件下会被缓存, 属于过滤上下文
must_not 可包含多个过滤条件,每个条件均不满足的文档才能被搜索到,每个过滤条件不计算相关度得分,结果在一定条件下会被缓存, 属于过滤上下文

must

1
2
3
4
5
6
7
8
9
10
11
12
13
# 两个条件都需要满足
curl -X GET -u elastic:123456 -k 'https://127.0.0.1:9200/shopping/_search?pretty' \
-H 'Content-Type: application/json' \
-d '{
"query":{
"bool":{
"must":[
{"match":{"category":"electronics"}},
{"match":{"desc":"公园"}}
]
}
}
}'

must_not

1
2
3
4
5
6
7
8
9
10
11
12
13
# 两个条件都不满足
curl -X GET -u elastic:123456 -k 'https://127.0.0.1:9200/shopping/_search?pretty' \
-H 'Content-Type: application/json' \
-d '{
"query":{
"bool":{
"must_not":[
{"match":{"category":"electronics"}},
{"match":{"desc":"公园"}}
]
}
}
}'

should

1
2
3
4
5
6
7
8
9
10
11
12
13
# 两个条件满足一个即可
curl -X GET -u elastic:123456 -k 'https://127.0.0.1:9200/shopping/_search?pretty' \
-H 'Content-Type: application/json' \
-d '{
"query":{
"bool":{
"should":[
{"match":{"category":"electronics"}},
{"match":{"desc":"公园"}}
]
}
}
}'

filter

1
2
3
4
5
6
7
8
9
10
11
12
13
# filter中的条件为非 match,即不能是全文检索
curl -X GET -u elastic:123456 -k 'https://127.0.0.1:9200/shopping/_search?pretty' \
-H 'Content-Type: application/json' \
-d '{
"query":{
"bool":{
"filter":[
{"term":{"category":"electronics"}},
{"range":{"price":{"gte":20}}}
]
}
}
}'

分页与排序

1
2
3
4
5
6
7
8
9
10
11
# from: 从第几条开始,默认0
# size: 取多少条
# sort: 排序,默认为按文档id升序
curl -X GET -u elastic:123456 -k 'https://127.0.0.1:9200/shopping/_search?pretty' \
-H 'Content-Type: application/json' \
-d '{
"query":{"range":{"price":{"gte":20,"lte":30}}},
"sort":[{"price":"address"}],
"from":0,
"size":5
}'

只返回部分字段

1
2
3
4
5
6
7
# _source: 指定要返回的字段列表
curl -X GET -u elastic:123456 -k 'https://127.0.0.1:9200/shopping/_search?pretty' \
-H 'Content-Type: application/json' \
-d '
{"query":{"range":{"price":{"gte":20,"lte":30}}},
"_source":["category","title","price"]
}'

高亮显示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 高亮显示仅支持全文检索字段
curl -X GET -u elastic:123456 -k 'https://127.0.0.1:9200/shopping/_search?pretty' \
-H 'Content-Type: application/json' \
-d '{
"query": {
"multi_match": {
"fields": ["title","address"],
"query": "公园shirt"
}
},
"highlight": {
"post_tags": ["</span>"],
"pre_tags": ["<span style='color:red'>"],
"fields": {
"*":{}
}
}
}'

地理空间位置查询

  • 地理空间位置查询是数据库和搜索系统中的一个重要特性,特别是在地理信息系统(GIS)和位置服务中。它允许用户基于地理位置信息来搜索和过滤数据。在Elasticsearch这样的全文搜索引擎中,地理空间位置查询被广泛应用,例如在旅行、房地产、物流和零售等行业,用于提供基于位置的搜索功能。

  • 在Elasticsearch中,地理空间数据通常存储在geo_point字段类型中。这种字段类型可以存储纬度和经度坐标,用于表示地球上的一个点。

示例

  • 创建一个索引,并添加一个geo_point字段:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
curl -X PUT -u elastic:123456 -k 'https://127.0.0.1:9200/tourist_spots' \
-H 'Content-Type: application/json' \
-d '{
"mappings": {
"properties": {
"name": {
"type": "text",
"analyzer": "ik_max_word",
"search_analyzer": "ik_max_word"
},
"location": {
"type": "geo_point"
}
}
}
}'
  • 插入数据

1
2
3
4
5
6
7
8
9
10
11
curl -X POST -u elastic:123456 -k 'https://127.0.0.1:9200/tourist_spots/_bulk' \
-H 'Content-Type: application/json' \
-d '{"index":{}}
{"name":"雷峰塔","location":{"lat":30.2615,"lon":120.1480}}
{"index":{}}
{"name":"西湖","location":{"lat":30.2614,"lon":120.1479}}
{"index":{}}
{"name":"苏堤春晓","location":{"lat":30.2624,"lon":120.1708}}
'
# lat: 纬度
# lon: 经度
  • 查询数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# 查询杭州西湖5km附近的景点
# 雷峰塔 - 位于西湖附近,距离约2.8公里。
# 苏堤春晓 - 位于西湖边,距离西湖中心约1公里。
curl -X GET -u elastic:123456 -k 'https://127.0.0.1:9200/tourist_spots/_search?pretty' \
-H 'Content-Type: application/json' \
-d '{
"query": {
"bool": {
"must": {
"match_all": {}
},
"filter": {
"geo_distance": {
"distance": "5km",
"distance_type": "arc",
"location": {
"lat": 30.2614,
"lon": 120.1479
}
}
}
}
}
}'

# distance: 5km 表示距离为5公里
# distance_type: arc, plane, sloppy_arc,
# arc: 默认值,使用haversine公式计算距离,结果是精确的,但计算速度较慢。
# plane: 使用平面直角坐标系计算距离,结果是粗略的,但计算速度更快。
# sloppy_arc: 使用haversine公式计算距离,但允许误差。
# location: 搜索条件

向量搜索

  • Elasticsearch 8.x 引入了一个重要的新特性:向量检索(Vector Search),特别是通过KNN(K-Nearest Neighbors)算法支持向量近邻检索。这一特性使得Elasticsearch在机器学习、数据分析和推荐系统等领域的应用变得更加广泛和强大。

  • 向量检索的基本思路是,将文档(或数据项)表示为高维向量,并使用这些向量来执行相似性搜索。在Elasticsearch中,这些向量被存储在dense_vector类型的字段中,然后使用KNN算法来找到与给定向量最相似的其他向量。

示例

  • 创建索引

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
curl -X PUT -u elastic:123456 -k 'https://127.0.0.1:9200/image-index' \
-H 'Content-Type: application/json' \
-d '{
"mappings": {
"properties": {
"image-vector": {
"type": "dense_vector",
"dims": 3
},
"title": {
"type": "text"
},
"file-type": {
"type": "keyword"
},
"my_label": {
"type": "text"
}
}
}
}'
# dims: 3 表示3维向量,最高支持2048
  • 添加数据

1
2
3
4
5
6
7
8
9
curl -X POST -u elastic:123456 -k 'https://127.0.0.1:9200/image-index/_bulk' \
-H 'Content-Type: application/json' \
-d '{ "index": {} }
{ "image-vector": [-5, 9, -12], "title": "Image A", "file-type": "jpeg", "my_label": "red" }
{ "index": {} }
{ "image-vector": [10, -2, 3], "title": "Image B", "file-type": "png", "my_label": "blue" }
{ "index": {} }
{ "image-vector": [4, 0, -1], "title": "Image C", "file-type": "gif", "my_label": "red" }
'
  • 向量检索

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
curl -X POST -u elastic:123456 -k 'https://127.0.0.1:9200/image-index/_search?pretty' \
-H 'Content-Type: application/json' \
-d '{
"query":{ "match_all": {} },
"knn": {
"field": "image-vector",
"query_vector": [-5, 10, -12],
"k": 10,
"num_candidates": 100
},
"fields": [ "title", "file-type" ]
}'

# query: 搜索条件,这里可以不加这个
# knn: 8.8.1 版本开始默认支持
# field: 搜索向量字段
# query_vector: 搜索向量
# k: 搜索结果数量
# num_candidates: 搜索候选数量,用于优化性能
# fields: 搜索结果返回字段