Elasticsearch
是面向文档型数据库,一条数据在这里就是一个文档。 为了方便理解,可以将 Elasticsearch
里存储文档数据和关系型数据库MySQL
存储数据的概念进行一个类比。
Elasticsearch
里的 Index
可以看做一个库,而 Types
相当于表, Documents
则相当于表的行。
但这里Types
的概念已经被逐渐弱化, Elasticsearch 6.X
中,一个 index
下已经只能包含一个type
,Elasticsearch 7.X
中 , Type
的概念已经被删除了。
有了index
库,等于有了数据库中的database
。下面就需要建索引库中的映射,类似于数据库中的表结构。
创建数据库表需要设置字段名称,类型,长度,约束等,索引库也一样,需要知道这个类型下有哪些字段,每个字段有哪些约束信息,这就叫做映射(mapping
)
在Postman
中,向ES
服务器发 PUT
请求:http://127.0.0.1:9200/student/_mapping
{
"properties":{
"name":{
"type": "text",
"index": true # 可以索引
},
"sex":{
"type": "text",
"index": false # 不可以索引,后续查询时,不能查询没有索引的属性
},
"age":{
"type": "long",
"index": false
}
}
}
注:创建映射时,索引要创建好,不然会报
index_not_found_exception
错
映射数据说明:
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
:分词器在Postman
中,向 ES
服务器发 GET
请求:http://127.0.0.1:9200/student/_mapping
刚创建索引时,是没有映射信息的,如下所示:mapping
为空
{
"nba": {
"aliases": {},
"mappings": {},
"settings": {
"index": {
"creation_date": "1650278315803",
"number_of_shards": "1",
"number_of_replicas": "1",
"uuid": "cQTAD1btTpmDcfMYzX4TtA",
"version": {
"created": "7080099"
},
"provided_name": "nba"
}
}
}
}
在Postman
中,向 ES
服务器发PUT
请求:http://127.0.0.1:9200/students
{
"settings":{},
"mappings":{
"properties":{
"name":{
"type": "text",
"index": true
},
"sex":{
"type": "text",
"index": false
},
"age":{
"type": "long",
"index": false
}
}
}
}
Elasticsearch
提供了基于 JSON
提供完整的查询 DSL
来定义查询,准备测试数据:
# 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": "bob",
"nickName":"bob",
"sex":"难",
"age":28
}
# POST /student/_doc/1004
{
"name": "Hellen",
"nickName":"Hellen",
"sex":"女",
"age":18
}
# POST /student/_doc/1005
{
"name": "Jordan",
"nickName":"Jordan",
"sex":"男",
"age":45
}
在Postman
中,向ES
服务器发 GET
请求:http://127.0.0.1:9200/student/_search
# 此方式查询,并不会返回所有数据,默认10条
{
"query": {
"match_all": {}
}
}
# 此方式会返回50条数据
{
"size":50
}
{
"took": 592, # 查询话费时间,单位毫秒
"timed_out": false, # 是否超时
"_shards": { # 分片信息
"total": 1, # 分片总数
"successful": 1, # 成功
"skipped": 0, # 忽略
"failed": 0 # 失败
},
"hits": { # 搜索命中结果
"total": { # 搜索条件匹配的文档总数
"value": 11, # 总命中计数的值
"relation": "eq" # 计数规则,eq表示计数准确,gte表示计数不准确
},
"max_score": 1.0, # 匹配度分值
"hits": [ # 命中结果集合
{
"_index": "student",
"_type": "_doc",
"_id": "1001",
"_score": 1.0,
"_source": {
"name": "zhangsan",
"nickName": "zhangsan",
"sex": "男",
"age": 30
}
},
...
]
}
}
使用该参数查询,每次只能返回10条数据,并不能返回全部数据。
match
匹配类型查询,会把查询条件进行分词,然后进行查询,多个词条之间是 or 的关系
在Postman
中,向 ES
服务器发 GET
请求:http://127.0.0.1:9200/student/_search
# 查询条件,搜索name为Kobe的数据
{
"query":{
"match": {
"name":"Kobe"
}
}
}
multi_match
与 match
类似,不同的是它可以在多个字段中查询
在Postman
中,向 ES
服务器发 GET
请求:http://127.0.0.1:9200/student/_search
{
"query":{
"multi_match": {
"query": "zhangsan",
"fields": ["name","nickName"]
}
}
}
term
查询,精确的关键词匹配查询,不对查询条件进行分词
在Postman
中,向 ES
服务器发 GET
请求:http://127.0.0.1:9200/student/_search
{
"query": {
"term": {
"name": {
"value": "zhangsan"
}
}
}
}
terms
查询和 term
查询一样,但它允许指定多值进行匹配,如果这个字段包含了指定值中的任何一个值,那么这个文档满足条件,类似于mysql
的 in
在Postman 中,向 ES 服务器发 GET 请求:http://127.0.0.1:9200/student/_search
{
"query": {
"term": {
"name": ["zhangsan","Kobe"]
}
}
}
注意:此处传入的大小写不一样,结果却不同
默认情况下,Elasticsearch
在搜索的结果中,会把文档中保存在 _source
的所有字段都返回,如果只想获取其中的部分字段,可以添加_source
的过滤。
在Postman
中,向 ES
服务器发 GET
请求:http://127.0.0.1:9200/student/_search
{
"_source": [
"name",
"nickName"
],
"query": {
"terms": {
"name": [
"zhangsan"
]
}
}
}
也可以通过:
includes
:来指定想要显示的字段,来指定想要显示的字段
excludes
:来指定不想要显示的字段,来指定不想要显示的字段
在Postman
中,向ES
服务器发GET
请求:http://127.0.0.1:9200/student/_search
{
"_source": {
"includes": [
"name",
"nickName"
]
},
"query": {
"terms": {
"name": [
"zhangsan"
]
}
}
}
bool
把各种其它查询通过 must
(必须 )、 must_ not
(必须不)、 should
(应该)的方式进行组合
在Postman
中,向ES
服务器发GET
请求:http://127.0.0.1:9200/student/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"name": "zhangsan"
}
}
],
"must_not": [
{
"match": {
"age": "40"
}
}
],
"should": [
{
"match": {
"sex": "男"
}
}
]
}
}
}
此处age和sex不能通过索引去查询,因为在创建映射关系时候是index属性被设置为false
range
查询找出那些落在指定区间内的数字或者时间,range
查询允许以下字符
操作符 | 说明 |
---|---|
gt | 大于 |
gte | 大于等于 |
lt | 小于 |
lte | 小于等于 |
在Postman
中,向 ES
服务器发 GET
请求:http://127.0.0.1:9200/student/_search
{
"query":{
"range":{
"age":{
"gte":30,
"lte":35
}
}
}
}
模糊查询返回包含与搜索字词相似的字词的文档。编辑距离是将一个术语转换为另一个术语所需的一个字符更改的次数。这些更改可以包括:
为了找到相似的术语,fuzzy
查询会在指定的编辑距离内创建一组搜索词的所有可能的变体或扩展,然后查询返回每个扩展完全匹配。通过fuzziness
修改编辑距离,一般使用默认值 AUTO
,根据术语的长度生成编辑距离。
在Postman
中,向 ES
服务器发 GET
请求:http://127.0.0.1:9200/student/_search
{
"query":{
"fuzzy":{
"name":{
"value":"zhangsan",
"fuzziness": 0
}
}
}
}
sort
可以按照不同的字段进行排序,并且通过 order
指定排序的方式, desc
降序, asc
升序
在Postman
中,向 ES
服务器发 GET
请求:http://127.0.0.1:9200/student/_search
{
"query":{
"fuzzy":{
"name":{
"value":"zhangsan",
"fuzziness": 2
}
}
},
"sort":[{
"age":{
"order":"desc"
}
}]
}
假定想要结合使用age
和 _id
进行查询,并且匹配的结果首先按照年龄排序,然后按照_id
排序
在Postman
中,向 ES
服务器发 GET
请求:http://127.0.0.1:9200/student/_search
{
"size":50,
"sort":[{
"age":{
"order":"desc"
},
"_id":{
"order":"asc"
}
}]
}
在进行关键字搜索时,搜索出的内容中的关键字会显示不同的颜色,称之为高亮。
Elasticsearch
可以对查询内容中的关键字部分,进行标签和样式高亮的设置。在使用match
查询的同时,加上一个 highlight
属性:
pre_tags
:前置标签post_tags
:后置标签fields
:需要高亮的字段title
:这里声明 title 字段需要高亮,后面可以为这个字段设置特有配置, 也可以空在Postman
中,向 ES
服务器发 GET
请求:http://127.0.0.1:9200/student/_search
{
"query": {
"multi_match": {
"query": "zhangsan",
"fields": [
"name",
"nickName"
]
}
},
"highlight": {
"pre_tags": "",
"post_tags": "",
"fields": {
"name": {},
"nickName": {}
}
}
}
from
:当前页的起始索引,默认从 0
开始,from = (pageNum 1) * size
size
:每页显示多少条
在Postman
中,向 ES
服务器发 GET
请求:http://127.0.0.1:9200/student/_search
聚合允许使用者对ES
文档进行统计分析,类似与关系型数据库中的group by
,当然还有很多其他的聚合,例如取最大值、平均值等等。
在Postman
中,向 ES
服务器发 GET
请求:http://127.0.0.1:9200/student/_search
{
"aggs": {
"max_age": {
"max": {
"field": "age"
}
}
},
"size": 0
}
{
"aggs": {
"min_age": {
"min": {
"field": "age"
}
}
},
"size": 0
}
{
"aggs": {
"sum_age": {
"sum": {
"field": "age"
}
}
},
"size": 0
}
{
"aggs": {
"avg_age": {
"avg": {
"field": "age"
}
}
},
"size": 0
}
{
"aggs": {
"distinct_age": {
"cardinality": {
"field": "age"
}
}
},
"size": 0
}
{
"aggs": {
"stats_age": {
"stats": {
"field": "age"
}
}
},
"size": 0
}
桶聚和相当于sql
中的 group by
语句
在Postman
中,向 ES
服务器发 GET
请求 http://127.0.0.1:9200/student/_search
# 按年龄分租统计
{
"aggs": {
"age_groupby": {
"terms": {
"field": "age"
}
}
},
"size": 0
}
# 按年龄分租统计,再进行求和
{
"aggs": {
"age_groupby": {
"terms": {
"field": "age"
},
"aggs": {
"sum_age": {
"sum": {
"field": "age"
}
}
}
}
},
"size": 0
}