ES为提供了一套HTTP RESTful API,开发和运维人员可以直接调用这些API来配置和访问ES服务。 这些API的功能十分丰富,从集群监控、运维管理到应用开发所需的索引、文档相关操作。本文将从应用开发的角度整理ES应用开发人员应该熟练掌握的API。

1.索引的创建、修改和删除

创建索引PUT /<index-name>,例:

 1PUT /book-0.1.0
 2{
 3    "aliases": {
 4        "book":{}
 5    },
 6    "settings": {
 7        "analysis": {
 8            "normalizer": {
 9                "lowercase": {
10                    "type": "custom",
11                    "char_filter": [],
12                    "filter": ["lowercase"]
13                }
14            }
15        }
16    },
17    "mappings": {
18        "properties": {
19            "name": {
20                "type": "keyword",
21                "normalizer": "lowercase"
22            },
23            "price": {
24                "type": "double"
25            },
26            "summary": {
27                "type": "text",
28                "analyzer": "ik_max_word"
29            },
30            "author": {
31                "type": "keyword"
32            },
33            "pubDate": {
34                "type": "date"
35            }
36        }
37    }
38}

实践中在创建索引时,索引的名称一般会带上版本号,同时将不带版本号的名称设置为索引的别名(alias),开发中对索引文档的操作都是基于别名。 通过索引别名可以优雅的解决两个版本索引之间的无缝切换问题。

删除索引DELETE /<index-name>,例:

1DELETE /book-0.1.0

查看索引信息GET /<index-name>,例:

1GET /book-0.1.0

在应用开发的各个迭代过程中,经常需要对一个索引的mapping结构进行调整。 如果调整结构的需求是增加新的字段,可以直接调用API增加,如果是修改现有字段或删除现有字段,则只能通过创建新mapping结构的索引并重新reindex数据的方式实现。 调用API增加新字段举例如下:

1PUT /book-0.1.0/_mapping
2{
3    "properties": {
4        "pages": {
5            "type": "integer"
6        }
7    }
8}

2.文档的创建

索引创建好后就可以直接向索引中添加数据了。

1PUT /<index-name>/_doc/<_id>
2
3POST /<index-name>/_doc/
4
5PUT /<index-name>/_create/<_id>
6
7POST /<index-name>/_create/<_id>
 1POST /book/_doc
 2{
 3  "name": "天龙八部",
 4  "author": "金庸",
 5  "pages": 1978,
 6  "price": 96.0,
 7  "pubDate": "1994-05-01",
 8  "summary": "天龙八部乃金笔下的一部长篇小说,与《射雕》,《神雕》等 几部长篇小说一起被称为可读性最高的金庸小说。《天龙》的故事情节曲折,内容丰富,也曾多次被改编为电视作品。是金庸作品中集大成的一部。故事以北宋末年动荡的社会环境为背景,展开波澜壮阔的历史画卷,塑造了乔峰、段誉、 虚竹、慕容复等形象鲜明的人物,成为武侠史上的经典之作。"
 9}
10
11输出:
12{
13  "_index" : "book-0.1.0",
14  "_type" : "_doc",
15  "_id" : "y2W-mHkB3xk21-h8U9AP",
16  "_version" : 1,
17  "result" : "created",
18  "_shards" : {
19    "total" : 2,
20    "successful" : 2,
21    "failed" : 0
22  },
23  "_seq_no" : 0,
24  "_primary_term" : 1
25}

文档创建成功后,会返回一个包含_id的json数据,_id即为刚刚创建的文档的ID由ES自动生成,唯一标识一个文档。 POST /<target>/_doc/这个API不具有幂等性,多次请求会创建_id不同的,但文档其他字段相同的重复数据。

可以在创建文档时手动指定文档ID:

1POST /book/_doc/10001
2{
3  "name": "天龙八部",
4  "author": "金庸",
5  "pages": 1978,
6  "price": 96.0,
7  "pubDate": "1994-05-01",
8  "summary": "天龙八部乃金笔下的一部长篇小说,与《射雕》,《神雕》等 几部长篇小说一起被称为可读性最高的金庸小说。《天龙》的故事情节曲折,内容丰富,也曾多次被改编为电视作品。是金庸作品中集大成的一部。故事以北宋末年动荡的社会环境为背景,展开波澜壮阔的历史画卷,塑造了乔峰、段誉、 虚竹、慕容复等形象鲜明的人物,成为武侠史上的经典之作。"
9}

文档创建成功后,返回的_id为我们指定的ID值,多次发出这个创建请求,返回的结果是相同的,只是返回数据版本_version会增加。 操作是幂等的,也可以将上面的POST请求方式换成PUT请求。另外可以使用PUT /<index-name>/_create/<_id>POST /<index-name>/_create/<_id>创建文档时,如果_id已经存在时会失败并报版本冲突的错误,实际根据具体的需求选择使用哪个API。

3.文档的查询

使用GET <index-name>/_doc/<_id>API查询指定ID的文档:

例如:

 1GET /book/_doc/10001
 2
 3输出:
 4{
 5  "_index" : "book-0.1.0",
 6  "_type" : "_doc",
 7  "_id" : "10001",
 8  "_version" : 5,
 9  "_seq_no" : 7,
10  "_primary_term" : 1,
11  "found" : true,
12  "_source" : {
13    "name" : "天龙八部",
14    "author" : "金庸",
15    "pages" : 1978,
16    "price" : 96.0,
17    "pubDate" : "1994-05-01",
18    "summary" : ......
19  }
20}

使用GET <index-name>/_search查询所有的文档数据:

1GET /book/_search

4.文档的更新和删除

更新文档包含两种情况,一种是完全覆盖性更新,另一种是局部性更新。

先来看完全覆盖性更新:

1PUT /book/_doc/10001
2{
3  "name": "天龙八部",
4  "author": "金庸",
5  "pages": 1978,
6  "price": 96.0,
7  "pubDate": "1994-05-01",
8  "summary": ""
9}

再来看局部性更新:

1POST /book/_update/10001
2{
3    "doc": {
4        "name": "《天龙八部》"
5    }
6}

文档的删除:

1DELETE /book/_update/10001

5.条件查询、分页和排序

前面已经介绍了文档的增、删、改、查,ES的优势还是在查询上。

简单的条件查询、分页和排序如下例:

 1GET /book/_search
 2{
 3  "query": {
 4    "match": {
 5      "author": "金庸"
 6    }
 7  },
 8  "from": 0,
 9  "size": 5,
10  "sort": [
11    {
12      "price": {
13        "order": "desc"
14      }
15    }
16  ]
17}

6.多条件查询和范围查询

多条件查询如下例:

 1# 多条件同时成立
 2GET /book/_search
 3{
 4  "query": {
 5    "bool": {
 6      "must": [
 7        {
 8          "match": {
 9            "author": "金庸"
10          }
11        },
12        {
13          "match": {
14            "pages": 1978
15          }
16        }
17      ]
18    }
19  }
20}
21
22# 多条件满足其一即可
23GET /book/_search
24{
25  "query": {
26    "bool": {
27      "should": [
28        {
29          "match": {
30            "author": "金庸"
31          }
32        },
33        {
34          "match": {
35            "pages": 1978
36          }
37        }
38      ]
39    }
40  }
41}

范围查询如下例:

 1GET /book/_search
 2{
 3  "query": {
 4    "bool": {
 5      "must": [
 6        {
 7          "match": {
 8            "author": "金庸"
 9          }
10        },
11        {
12          "range": {
13            "price": {
14              "gte":50,
15              "lte": 100
16            }
17          }
18        }
19      ]
20    }
21  }
22}

7.全文检索与完全匹配

文档字段为text类型时,会将查询关键字进行分词并在倒排索引中进行匹配。

1GET /book/_search
2{
3  "query": {
4    "match": {
5      "summary": "北宋射雕"
6    }
7  }
8}

完全匹配:

1GET /book/_search
2{
3  "query": {
4    "match_phrase": {
5      "author": "金庸"
6    }
7  }
8}

高亮显示:

 1GET /book/_search
 2{
 3  "query": {
 4    "match": {
 5      "summary": "北宋射雕"
 6    }
 7  },
 8  "highlight": {
 9    "fields": {
10      "summary": {}
11    }
12  }
13}

8.聚合查询

下面的例子,使用aggs进行聚合查询,设置"size": 0只返回聚合统计结果,不要返回查询的hits结果。

 1GET /book/_search
 2{
 3  "aggs": {
 4    "author_agg_name": {
 5      "terms": {
 6        "field": "author"
 7      }
 8    }
 9  },
10  "size": 0
11}

例如查询作者为金庸的所有图书的平均价格:

 1GET /book/_search
 2{
 3  "query": {
 4    "match_phrase": {
 5      "author": "金庸"
 6    }
 7  }, 
 8  "aggs": {
 9    "avg_price": {
10      "avg": {
11        "field": "price"
12      }
13    }
14  },
15  "size": 0
16}

参考