通过上一篇我们已经了解了es的介绍和es文档的操作,本文将介绍es的映射管理和各种高级查询,通过对es的各种查询能够更加了解es的操作
一、映射管理
映射类似于数据库中的表结构
-
创建映射
创建映射之前,应当先创建索引
PUT请求,http://127.0.0.1:9200/student
然后向 ES 服务器发 PUT 请求 :http://127.0.0.1:9200/student/_mapping
请求体为:
json{ "properties": { "name": { "type": "text", "index": true }, "sex": { "type": "text", "index": false }, "age": { "type": "long", "index": false } } }
返回结果为:
json{ "acknowledged": true }
注意:
json"sex": { "type": "text", "index": false }
index = false 会导致无法查询
映射数据说明:
-
字段名:任意填写,下面指定许多属性,例如:title、subtitle、images、price
-
type:类型,Elasticsearch 中支持的数据类型非常丰富,说几个关键的:
-
String 类型,又分两种:
- text:可分词
- keyword:不可分词,数据会作为完整字段进行匹配
-
Numerical:数值类型,分两类
- 基本数据类型:long、integer、short、byte、double、float、half_float
- 浮点数的高精度类型:scaled_float
-
Date:日期类型
-
Array:数组类型
-
Object:对象
-
-
index:是否索引,默认为 true,也就是说你不进行任何配置,所有字段都会被索引。 true:字段会被索引,则可以用来进行搜索 false:字段不会被索引,不能用来搜索
-
store:是否将数据进行独立存储,默认为 false 原始的文本会存储在source 里面,默认情况下其他提取出来的字段都不是独立存储 的,是从source 里面提取出来的。当然你也可以独立的存储某个字段,只要设置 "store": true 即可,获取独立存储的字段要比从_source 中解析快得多,但是也会占用 更多的空间,所以要根据实际业务需求来设置。
-
analyzer:分词器,这里的 ik_max_word 即使用 ik 分词器
-
查看映射
向 ES 服务器发 GET 请求 :http://127.0.0.1:9200/student/_mapping
响应结果如下:
json{ "student": { "aliases": {}, "mappings": { "properties": { "age": { "type": "long" }, "name": { "type": "text" }, "sex": { "type": "text", "index": false } } }, "settings": { "index": { "creation_date": "1693989843117", "number_of_shards": "1", "number_of_replicas": "1", "uuid": "17zS0l19SdmRqWLi-j_6bQ", "version": { "created": "7080099" }, "provided_name": "student" } } } }
-
索引映射关联
意思就是在创建索引的同时,指定映射
向 ES 服务器发 PUT 请求 :http://127.0.0.1:9200/student1
请求体:
json{ "settings": {}, "mappings": { "properties": { "name": { "type": "text", "index": true }, "sex": { "type": "text", "index": true }, "age": { "type": "long", "index": true } } } }
响应结果:
json{ "acknowledged": true, "shards_acknowledged": true, "index": "student1" }
-
映射的删除
在删除索引的同时,映射也会被删除
二、高级查询
Elasticsearch 提供了基于 JSON 提供完整的查询 DSL 来定义查询
定义数据 :
bash
# POST /student/_doc/1001
{
"name":"zhangsan",
"nickname":"zhangsan",
"sex":"男",
"age":30
}
# POST /student/_doc/1002
{
"name":"lisi",
"nickname":"lisi",
"sex":"男",
"age":20
}
# POST /student/_doc/1003
{
"name":"wangwu",
"nickname":"wangwu",
"sex":"女",
"age":40
}
# POST /student/_doc/1004
{
"name":"zhangsan1",
"nickname":"zhangsan1",
"sex":"女",
"age":50
}
# POST /student/_doc/1005
{
"name":"zhangsan2",
"nickname":"zhangsan2",
"sex":"女",
"age":30
}
1. 查询所有文档
向 ES 服务器发 GET 请求 :http://127.0.0.1:9200/student/_search
无请求体也会返回所有数据,默认十条
或者使用请求体,但结果是一样的:
json
{
"query": {
"match_all": {}
}
}
2. 匹配查询
发 GET 请求 :http://127.0.0.1:9200/student/_search
多个词条之间是or的关系
json
{
"query": {
"match": {
"name":"zhangsan,lisi"
}
}
}
响应内容:
json
{
"took": 47,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 2,
"relation": "eq"
},
"max_score": 1.3862942,
"hits": [
{
"_index": "student",
"_type": "_doc",
"_id": "1001",
"_score": 1.3862942,
"_source": {
"name": "zhangsan",
"nickname": "zhangsan",
"sex": "男",
"age": 30
}
},
{
"_index": "student",
"_type": "_doc",
"_id": "1002",
"_score": 1.3862942,
"_source": {
"name": "lisi",
"nickname": "lisi",
"sex": "男",
"age": 20
}
}
]
}
}
3. 字段匹配查询
multi_match 与 match 类似,不同的是它可以在多个字段中查询。
在 Postman 中,向 ES 服务器发 GET 请求 :http://127.0.0.1:9200/student/_search
json
{
"query": {
"multi_match": {
"query": "zhangsan",
"fields": ["name", "nickname"]
}
}
}
响应结果为:
json
{
"took": 47,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"max_score": 1.3862942,
"hits": [
{
"_index": "student",
"_type": "_doc",
"_id": "1001",
"_score": 1.3862942,
"_source": {
"name": "zhangsan",
"nickname": "zhangsan",
"sex": "男",
"age": 30
}
}
]
}
}
4. 关键字匹配查询
json
{
"query": {
"term": {
"name": {
"value": "zhangsan"
}
}
}
}
5. 多关键字精确查询
json
{
"query": {
"terms": {
"name": ["zhangsan", "lisi"]
}
}
}
6. 指定查询字段
json
{
"_source": ["name", "nickname"],
"query": {
"terms": {
"nickname": ["zhangsan"]
}
}
}
响应结果:
json
{
"took": 35,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"max_score": 1.0,
"hits": [
{
"_index": "student",
"_type": "_doc",
"_id": "1001",
"_score": 1.0,
"_source": {
"name": "zhangsan",
"nickname": "zhangsan"
}
}
]
}
}
7. 过滤字段
includes:来指定想要显示的字段
excludes:来指定不想要显示的字段
包含请求体:
json
{
"_source": {
"includes": ["name", "nickname"]
},
"query": {
"terms": {
"nickname": ["zhangsan"]
}
}
}
不包含请求体:
json
{
"_source": {
"excludes": ["name", "nickname"]
},
"query": {
"terms": {
"nickname": ["zhangsan"]
}
}
}
8. 组合查询
查询名字是 zhangsan,并且年龄不是40的
json
{
"query": {
"bool": {
"must": [{
"match": {
"name": "zhangsan"
}
}],
"must_not": [{
"match": {
"age": "40"
}
}]
}
}
}
9. 范围查询
操作符 | 说明 |
---|---|
gt | > |
gte | >= |
lt | < |
lte | <= |
例子:查询大于等于30并且小于等于50的
json
{
"query": {
"range": {
"age": {
"gte": 30,
"lte": 35
}
}
}
}
返回结果:
json
{
"took": 1017,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 2,
"relation": "eq"
},
"max_score": 1.0,
"hits": [
{
"_index": "student",
"_type": "_doc",
"_id": "1001",
"_score": 1.0,
"_source": {
"name": "zhangsan",
"nickname": "zhangsan",
"sex": "男",
"age": 30
}
},
{
"_index": "student",
"_type": "_doc",
"_id": "1005",
"_score": 1.0,
"_source": {
"name": "zhangsan2",
"nickname": "zhangsan2",
"sex": "女",
"age": 30
}
}
]
}
}
10. 模糊查询
fuzzy,fuzzy的查询不分词
有个偏移量,用户输入错误的内容,也可以查询到正确的结果
比如:用户想查询name等于zhangsan的数据,但手误打成了 zhangsn
json
{
"query": {
"fuzzy": {
"name": {
"value": "zhangsn"
}
}
}
}
返回结果
json
{
"took": 106,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 3,
"relation": "eq"
},
"max_score": 1.1882522,
"hits": [
{
"_index": "student",
"_type": "_doc",
"_id": "1001",
"_score": 1.1882522,
"_source": {
"name": "zhangsan",
"nickname": "zhangsan",
"sex": "男",
"age": 30
}
},
{
"_index": "student",
"_type": "_doc",
"_id": "1004",
"_score": 0.9902103,
"_source": {
"name": "zhangsan1",
"nickname": "zhangsan1",
"sex": "女",
"age": 50
}
},
{
"_index": "student",
"_type": "_doc",
"_id": "1005",
"_score": 0.9902103,
"_source": {
"name": "zhangsan2",
"nickname": "zhangsan2",
"sex": "女",
"age": 30
}
}
]
}
}
11. 单字段排序
sort 可以让我们按照不同的字段进行排序,并且通过 order 指定排序的方式。desc 降序,asc 升序
例子:
css
{
"query": {
"match": {
"name": "zhangsan"
}
},
"sort": [{
"age": {
"order": "desc"
}
}]
}
12. 多字段排序
使用 age 和 _score 进行查询,并且匹配的结果首先按照年龄排序,然后 按照相关性得分排序
css
{
"query": {
"match_all": {}
},
"sort": [{
"age": {
"order": "desc"
}
},
{
"_score": {
"order": "desc"
}
}
]
}
13. 高亮查询
Elasticsearch 可以对查询内容中的关键字部分,进行标签和样式(高亮)的设置。
在使用 match 查询的同时,加上一个 highlight 属性:
- pre_tags:前置标签
- post_tags:后置标签
- fields:需要高亮的字段
- title:这里声明 title 字段需要高亮,后面可以为这个字段设置特有配置,也可以空
json
{
"query": {
"match": {
"name": "zhangsan"
}
},
"highlight": {
"pre_tags": "<font color='red'>",
"post_tags": "</font>",
"fields": {
"name": {}
}
}
}
响应结果:
json
{
"took": 184,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"max_score": 1.3862942,
"hits": [
{
"_index": "student",
"_type": "_doc",
"_id": "1001",
"_score": 1.3862942,
"_source": {
"name": "zhangsan",
"nickname": "zhangsan",
"sex": "男",
"age": 30
},
"highlight": {
"name": [
"<font color='red'>zhangsan</font>"
]
}
}
]
}
}
14. 分页查询
css
{
"query": {
"match_all": {}
},
"sort": [{
"age": {
"order": "desc"
}
}],
"from": 0,
"size": 2
}
15. 聚合查询
可以通过聚合查询平均值,最大、最小值
比如,查询最大的年龄
json
{
"aggs": {
"max_age": {
"max": {
"field": "age"
}
}
},
"size": 0
}
注意这里的 size
为0,因为我们不需要查询的数据,只需要聚合的数据就可以
结果如下:
json
{
"took": 196,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 5,
"relation": "eq"
},
"max_score": null,
"hits": []
},
"aggregations": {
"max_age": {
"value": 50.0
}
}
}
可以看到最大的年龄为50
16. 桶聚合查询
相当于分组统计,group by
例如:分组统计每个年龄的数量
json
{
"aggs": {
"age_groupby": {
"terms": {
"field": "age"
}
}
},
"size": 0
}
响应结果:
json
{
"took": 67,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 5,
"relation": "eq"
},
"max_score": null,
"hits": []
},
"aggregations": {
"age_groupby": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": 30,
"doc_count": 2
},
{
"key": 20,
"doc_count": 1
},
{
"key": 40,
"doc_count": 1
},
{
"key": 50,
"doc_count": 1
}
]
}
}
}
三、总结
本文学习了对es映射的增删改查,还有对es的各种查询,已经基本满足使用需求。但更为复杂的查询还得查询官方文档或者技术博客。
这里放上官方文档链接,更为全面的查询,官方文档
ps:更多的时候,我们是不用自己去写查询条件的,有个插件叫 essql
,开源地址为:传送门,我们可以下载对应的版本,然后去写普通的sql就可以了,他可以帮我们转成 es的查询语句,方便快捷,简单易食用