「这是我参与11月更文挑战的第24天,活动详情查看:2021最后一次更文挑战」
ElasticSearch提供了一个REST API,通过HTTP通过JSON访问。
1、索引操作
1、索引的基本操作:
PUT /索引名 创建索引
DELETE /索引名 删除索引
DELETE /* 删除全部索引
GET /索引名 查看指定索引信息
GET /_cat/indices?v 查看全部索引信息,v表示查看表头信息
创建索引
命令:PUT /索引名,索引名不能出现大写字母
在创建索引时还可以指定配置信息:
查看全部索引信息
命令:GET /_cat/indices?v
命令:GET /索引名 ,查看指定索引信息
删除索引
删除某个所有,命令:DELETE /索引名
删除所有索引,命令:DELETE /*
2、映射操作
映射是存储在索引中的文档的大纲。它定义数据类型。
字段数据类型:
核心类型
- 字符串类型 string,text,keyword
- 整数类型 integer,long,short,byte
- 浮点类型 double,float,half_float,scaled_float
- 逻辑类型 boolean
- 日期类型 date
- 范围类型 range
- 二进制类型 binary
复合类型
- 数组类型 array
- 对象类型 object
- 嵌套类型 nested
- 地理类型 地理坐标类型 geo_point
- 地理地图 geo_shape
特殊类型
- IP类型 ip
- 范围类型 completion
- 令牌计数类型 token_count
- 附件类型 attachment
- 抽取类型 percolator
创建映射
创建过程如下:
创建完成后通过 GET /ems 命令查看ems索引的信息:可以查看到映射信息和配置信息
如果指向查看映射信息,就输入 GET /ems/_mapping 命令:
如果我们没有指定映射,那么ElasticSearch 会默认帮我们指定字段类型。
3、操作文档
3.1、文档的基本操作
ElasticSearch 提供Rest API 的增删改查操作说明:当使用特定映射对相应索引发出请求时,它有助于在索引中添加或更新JSON文档
method | url地址 | 描述 |
---|---|---|
PUT | localhost:9200/索引名称/类型名称/文档id | 创建文档(指定文档id) |
POST | localhost:9200/索引名称/类型名称 | 创建文档(随机文档id) |
POST | localhost:9200/索引名称/类型名称/文档id/_update | 修改文档 |
DELETE | localhost:9200/索引名称/类型名称/文档id | 删除文档 |
GET | localhost:9200/索引名称/类型名称/文档id | 通过文档id查询文档 |
POST | localhost:9200/索引名称/类型名称/_search | 查询所有数据 |
创建文档(指定文档id)
启动ElasticSearch、elasticsearch-head 和 Kibana。
1、创建一个文档,并指定文档id为1
自动创建索引:当请求将JSON对象添加到特定索引时,如果该索引不存在,那么会自动创建该索引以及该特定JSON对象的基础映射。
版本控制: 内部版本控制是以1开头的默认版本,每次更新都会增加,包括删除。
版本控制是一个实时过程,它不受实时搜索操作的影响。
操作类型:操作类型用于强制创建操作,这有助于避免覆盖现有文档。
2、查看创建的文档及索引
创建文档(随机文档id)
当在索引操作中未指定id时,Elasticsearch自动为文档生成id。
查看文档数据
API通过对特定文档执行get请求来帮助提取JSON对象。
命令:GET /索引/类型/文档id
这个操作是实时的,不受索引刷新率的影响。
还可以指定版本,然后 ElasticSearch 将仅提取该版本的文档。
还可以在请求中指定_all,以便 ElasticSearch 可以在每种类型中搜索该文档id,并且它将返回第一个匹配的文档。
还可以从该特定文档的结果中指定所需的字段。
根据规则查询文档信息:
如,查看text1索引下type1类型,name带有”万里“的文档信息:
命令:GET /text1/type1/_search?q=name:万里
删除文档
可以通过向**ElasticSearch **发送HTTP DELETE
请求来删除指定的索引,映射或文档。
可以看到id为1的文档已经被删除:
修改文档
在ems索引中创建一条文档:
修改方式一:
在创建文档命令中直接修改值,然后再次运行:
修改方式二(推荐使用):
使用post请求修改,保留原始数据的基础上进行更新,"doc"会先查询出原始文档的数据,然后拿doc里面的新字段来替换原始文档里的字段
修改后,查看修改后的文档信息:
使用post请求修改,不保留原始数据
修改后,查看修改后的文档信息:可以看到文档中只剩下name字段了
3.2、文档的复杂查询操作
3.2.1、环境搭建
添加四条文档数据
PUT /wanli/user/1
{
"name":"万里顾一程",
"age":"3",
"desc":"高级Java开发工程师",
"tags":["技术宅","钻研","运动"]
}
PUT /wanli/user/2
{
"name":"万里",
"age":"18",
"desc":"初级Java开发工程师",
"tags":["技术宅","直男","运动"]
}
PUT /wanli/user/3
{
"name":"神明",
"age":"6",
"desc":"ELK工程师",
"tags":["游戏","音乐","腼腆"]
}
PUT /wanli/user/4
{
"name":"方唐镜",
"age":"12",
"desc":"数据库管理员",
"tags":["诚实","踏实","热心"]
}
3.2.2、指定字段搜索
请求语句:
#在wanli索引的user类型中查询name 包含"万里"的文档
GET /wanli/user/_search
{
"query":{
"match": {
"name": "万里"
}
}
}
返回结果:
{
"took" : 23,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 2, #匹配到的文档总数
"relation" : "eq"
},
"max_score" : 1.605183, #最大分数,最符合结果的文档,从而优先显示
"hits" : [
{
"_index" : "wanli", #索引
"_type" : "user", #类型
"_id" : "2", #文档id
"_score" : 1.605183, #分数
"_source" : { #文档数据,可以遍历出来
"name" : "万里",
"age" : "18",
"desc" : "初级Java开发工程师",
"tags" : [
"技术宅",
"直男",
"运动"
]
}
},
{
"_index" : "wanli",
"_type" : "user",
"_id" : "1",
"_score" : 1.0892314,
"_source" : {
"name" : "万里顾一程",
"age" : "3",
"desc" : "高级Java开发工程师",
"tags" : [
"技术宅",
"钻研",
"运动"
]
}
}
]
}
}
返回结果说明:
-
took:执行整个搜索请求耗费了多少毫秒
-
timed_out :查询是否超时。
-
_shards :在查询中参与分片的总数,以及这些分片成功了多少个失败了多少个。
-
max_score:与查询所匹配文档的 _score 的最大值。
-
hits:返回结果中最重要的部分是 hits ,它 包含 total 字段来表示匹配到的文档总数
-
hits数组:一个 hits 数组包含所查询结果的前十个文档。在 hits 数组中每个结果包含文档的 _index 、 _type 、 _id ,加上 _source (文档数据)。这意味着我们可以直接从返回的搜索结果中使用整个文档。
-
_score :每个结果还有一个 _score ,它衡量了文档与查询的匹配程度。分数越大,匹配度越高,越先显示。
在_source 中返回指定字段(结果过滤):
请求语句:
GET /wanli/user/_search
{
"query":{
"match": {
"name": "万里"
}
},
"_source":["name","desc"]
}
返回结果:
{
"took" : 4,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 2,
"relation" : "eq"
},
"max_score" : 1.605183,
"hits" : [
{
"_index" : "wanli",
"_type" : "user",
"_id" : "2",
"_score" : 1.605183,
"_source" : {
"name" : "万里",
"desc" : "初级Java开发工程师"
}
},
{
"_index" : "wanli",
"_type" : "user",
"_id" : "1",
"_score" : 1.0892314,
"_source" : {
"name" : "万里顾一程",
"desc" : "高级Java开发工程师"
}
}
]
}
}
3.2.3、排序
请求语句:
#在wanli索引的user类型中查询name 包含"万里"的文档 ,并按年龄排序
GET /wanli/user/_search
{
"query":{
"match": {
"name":"万里"
}
},
"sort": [
{
"age.keyword": {
"order":"desc"
}
}
],
"from": 0,
"size": 1
}
返回结果:排序不会显示分数 _score
{
"took" : 13,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 2,
"relation" : "eq"
},
"max_score" : null,
"hits" : [
{
"_index" : "wanli",
"_type" : "user",
"_id" : "1",
"_score" : null,
"_source" : {
"name" : "万里顾一程",
"age" : "3",
"desc" : "高级Java开发工程师",
"tags" : [
"技术宅",
"钻研",
"运动"
]
},
"sort" : [
"3"
]
},
{
"_index" : "wanli",
"_type" : "user",
"_id" : "2",
"_score" : null,
"_source" : {
"name" : "万里",
"age" : "18",
"desc" : "初级Java开发工程师",
"tags" : [
"技术宅",
"直男",
"运动"
]
},
"sort" : [
"18"
]
}
]
}
}
3.3.4、分页
请求语句:
#在wanli索引的user类型中查询name 包含"万里"的文档 ,按年龄排序,并进行分页,每页显示一条数据
GET /wanli/user/_search
{
"query":{
"match": {
"name":"万里"
}
},
"sort": [
{
"age.keyword": {
"order":"desc"
}
}
],
"from": 0, #从第1条数据开始
"size": 1 #只显示一条数据
}
返回结果:
#! Deprecation: [types removal] Specifying types in search requests is deprecated.
{
"took" : 0,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 2,
"relation" : "eq"
},
"max_score" : null,
"hits" : [
{
"_index" : "wanli",
"_type" : "user",
"_id" : "1",
"_score" : null,
"_source" : {
"name" : "万里顾一程",
"age" : "3",
"desc" : "高级Java开发工程师",
"tags" : [
"技术宅",
"钻研",
"运动"
]
},
"sort" : [
"3"
]
}
]
}
}
3.3.5、bool布尔值查询
must :所有的条件都要符合(and)
在 wanli 索引的 user 类型中查询 name 包含"万里",并且年龄为18 的文档信息
GET /wanli/user/_search
{
"query":{
"bool": {
"must": [ #must :所有的条件都要符合(and)
{
"match": {
"name": "万里"
}
},
{
"match":{
"age": 18
}
}
]
}
}
}
返回结果:
#! Deprecation: [types removal] Specifying types in search requests is deprecated.
{
"took" : 0,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 2.809156,
"hits" : [
{
"_index" : "wanli",
"_type" : "user",
"_id" : "2",
"_score" : 2.809156,
"_source" : {
"name" : "万里",
"age" : "18",
"desc" : "初级Java开发工程师",
"tags" : [
"技术宅",
"直男",
"运动"
]
}
}
]
}
}
should:只要符合一个条件即可被查询(or)
在 wanli 索引的 user 类型中查询 name 包含"万里",或者年龄为3 的文档信息
GET /wanli/user/_search
{
"query":{
"bool": {
"should": [
{
"match": {
"name": "万里"
}
},
{
"match":{
"age": 3
}
}
]
}
}
}
返回结果:
#! Deprecation: [types removal] Specifying types in search requests is deprecated.
{
"took" : 3,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 2,
"relation" : "eq"
},
"max_score" : 2.2932043,
"hits" : [
{
"_index" : "wanli",
"_type" : "user",
"_id" : "1",
"_score" : 2.2932043,
"_source" : {
"name" : "万里顾一程",
"age" : "3",
"desc" : "高级Java开发工程师",
"tags" : [
"技术宅",
"钻研",
"运动"
]
}
},
{
"_index" : "wanli",
"_type" : "user",
"_id" : "2",
"_score" : 1.605183,
"_source" : {
"name" : "万里",
"age" : "18",
"desc" : "初级Java开发工程师",
"tags" : [
"技术宅",
"直男",
"运动"
]
}
}
]
}
}
must_not :查询出不符合条件的文档(not)
在 wanli 索引的 user 类型中查询 name 不包含"万里"的文档信息
GET /wanli/user/_search
{
"query":{
"bool": {
"must_not": [
{
"match": {
"name": "万里"
}
}
]
}
}
}
返回结果:
#! Deprecation: [types removal] Specifying types in search requests is deprecated.
{
"took" : 5,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 2,
"relation" : "eq"
},
"max_score" : 0.0,
"hits" : [
{
"_index" : "wanli",
"_type" : "user",
"_id" : "3",
"_score" : 0.0,
"_source" : {
"name" : "神明",
"age" : "6",
"desc" : "ELK工程师",
"tags" : [
"游戏",
"音乐",
"腼腆"
]
}
},
{
"_index" : "wanli",
"_type" : "user",
"_id" : "4",
"_score" : 0.0,
"_source" : {
"name" : "方唐镜",
"age" : "12",
"desc" : "数据库管理员",
"tags" : [
"诚实",
"踏实",
"热心"
]
}
}
]
}
}
3.3.6、范围查询
在 wanli 索引的 user 类型中查询 name 包含"万里",并且年龄大于10岁的文档信息
GET /wanli/user/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"name.keyword": "万里"
}
}
],
"filter": {
"range": {
"age.keyword": {
"gt": 10
}
}
}
}
}
}
-
gte 大于和等于
-
gt 大于
-
lte 小于和等于
-
lt 小于
返回结果:
{
"took" : 1,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 1.2039728,
"hits" : [
{
"_index" : "wanli",
"_type" : "user",
"_id" : "2",
"_score" : 1.2039728,
"_source" : {
"name" : "万里",
"age" : "18",
"desc" : "初级Java开发工程师",
"tags" : [
"技术宅",
"直男",
"运动"
]
}
}
]
}
}
3.3.7、匹配多个条件查询
请求语句:
#查询标签中带有 “男” 和 “技术” 的文档信息
GET /wanli/user/_search
{
"query" :{
"match":{
"tags": "男 技术" #中间空格隔开
}
}
}
返回结果:根据结果看出,越符合条件的查询结果分数越高
#! Deprecation: [types removal] Specifying types in search requests is deprecated.
{
"took" : 3,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 2,
"relation" : "eq"
},
"max_score" : 2.511242,
"hits" : [
{
"_index" : "wanli",
"_type" : "user",
"_id" : "2",
"_score" : 2.511242,
"_source" : {
"name" : "万里",
"age" : "18",
"desc" : "初级Java开发工程师",
"tags" : [
"技术宅",
"直男",
"运动"
]
}
},
{
"_index" : "wanli",
"_type" : "user",
"_id" : "1",
"_score" : 1.3440006,
"_source" : {
"name" : "万里顾一程",
"age" : "3",
"desc" : "高级Java开发工程师",
"tags" : [
"技术宅",
"钻研",
"运动"
]
}
}
]
}
}
3.3.8、完全匹配查询
term:代表完全匹配,也就是精确查询,搜索前不会再对搜索词进行分词拆解。
term 只能完完整整的匹配搜索词,不做任何改变的匹配。
创建一个映射:
PUT testdb
{
"mappings": {
"properties": {
"name":{
"type": "text"
},
"desc":{
"type": "keyword"
},
}
}
}
上面映射中指定 name 字段为 text 类型,desc 字段为 keyword 类型。
text 会被分词器解析,keyword不会被分词器解析。
添加文档数据:
PUT testdb/_doc/1
{
"name":"万里顾一程",
"desc":"当那一天真的来临"
}
PUT testdb/_doc/2
{
"name":"万里顾一程",
"desc":"当那一天真的真的来临"
}
使用 term查询 name字段:
GET testdb/_search
{
"query": {
"term": {
"name": "万"
}
}
}
返回结果:返回两条结果,因为name字段类型是text类型,分词器对name字段进行分词解析,把name中含有“万”的结果都返回了。
{
"took" : 1086,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 2,
"relation" : "eq"
},
"max_score" : 0.18232156,
"hits" : [
{
"_index" : "testdb",
"_type" : "_doc",
"_id" : "1",
"_score" : 0.18232156,
"_source" : {
"name" : "万里顾一程",
"desc" : "当那一天真的来临"
}
},
{
"_index" : "testdb",
"_type" : "_doc",
"_id" : "2",
"_score" : 0.18232156,
"_source" : {
"name" : "万里顾一程",
"desc" : "当那一天真的真的来临"
}
}
]
}
}
使用 term查询 desc 字段:
GET testdb/_search
{
"query": {
"term": {
"desc": "当那一天真的来临"
}
}
}
返回结果:只返回一条结果,因为desc字段类型是keyword类型,分词器对desc字段不会进行分词解析,只能完完整整的匹配搜索词。
{
"took" : 0,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 0.6931471,
"hits" : [
{
"_index" : "testdb",
"_type" : "_doc",
"_id" : "1",
"_score" : 0.6931471,
"_source" : {
"name" : "万里顾一程",
"desc" : "当那一天真的来临"
}
}
]
}
}
term和match的区别
match在匹配时会对所查找的关键词进行分词,然后按分词匹配查找,而term会直接对关键词进行查找。一般模糊查找的时候,多用match,而精确查找时可以使用term。
多个值进行完全匹配查询
GET testdb/_search
{
"query": {
"bool": {
"should": [
{
"term": {
"name": "万"
},
"term": {
"name": "万里"
}
}
]
}
}
}
3.3.9、高亮查询
默认高亮
查询请求语句:使用highlight
属性来实现结果高亮显示,需要的字段名称添加到fields
内即可,elasticsearch
会自动帮我们实现高亮。
GET wanli/user/_search
{
"query":{
"match": {
"name": "万里"
}
},
"highlight":{
"fields": {
"name": {}
}
}
}
返回结果:
#! Deprecation: [types removal] Specifying types in search requests is deprecated.
{
"took" : 61,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 2,
"relation" : "eq"
},
"max_score" : 1.605183,
"hits" : [
{
"_index" : "wanli",
"_type" : "user",
"_id" : "2",
"_score" : 1.605183,
"_source" : {
"name" : "万里",
"age" : "18",
"desc" : "初级Java开发工程师",
"tags" : [
"技术宅",
"直男",
"运动"
]
},
"highlight" : {
"name" : [
"<em>万</em><em>里</em>"
]
}
},
{
"_index" : "wanli",
"_type" : "user",
"_id" : "1",
"_score" : 1.0892314,
"_source" : {
"name" : "万里顾一程",
"age" : "3",
"desc" : "高级Java开发工程师",
"tags" : [
"技术宅",
"钻研",
"运动"
]
},
"highlight" : {
"name" : [
"<em>万</em><em>里</em>顾一程"
]
}
}
]
}
}
elasticsearch 会自动将检索结果用标签包裹起来,用于在页面中渲染。
自定义高亮显示
如果我们不想用em
标签,想用个p
标签时,可以自定义标签。
查询请求语句:pre_tags
用来实现我们的自定义标签的前半部分,在这里,我们也可以为自定义的标签添加属性和样式。post_tags
实现标签的后半部分,组成一个完整的标签。至于标签中的内容,则还是交给fields
来完成。
GET wanli/user/_search
{
"query":{
"match": {
"name": "万里"
}
},
"highlight":{
"pre_tags": "<p class='key',style:'color=red'>",
"post_tags": "</p>",
"fields": {
"name": {}
}
}
}
返回结果:
#! Deprecation: [types removal] Specifying types in search requests is deprecated.
{
"took" : 1,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 2,
"relation" : "eq"
},
"max_score" : 1.605183,
"hits" : [
{
"_index" : "wanli",
"_type" : "user",
"_id" : "2",
"_score" : 1.605183,
"_source" : {
"name" : "万里",
"age" : "18",
"desc" : "初级Java开发工程师",
"tags" : [
"技术宅",
"直男",
"运动"
]
},
"highlight" : {
"name" : [
"<p class='key',style:'color=red'>万</p><p class='key',style:'color=red'>里</p>"
]
}
},
{
"_index" : "wanli",
"_type" : "user",
"_id" : "1",
"_score" : 1.0892314,
"_source" : {
"name" : "万里顾一程",
"age" : "3",
"desc" : "高级Java开发工程师",
"tags" : [
"技术宅",
"钻研",
"运动"
]
},
"highlight" : {
"name" : [
"<p class='key',style:'color=red'>万</p><p class='key',style:'color=red'>里</p>顾一程"
]
}
}
]
}
}