Elasticsearch学习

前言

在互联网中,我们查询的信息主要包括文章、视频、图片、网站信息等等

根据数据的格式,我们会将数据分为三大类:

  • 结构化数据,通常表现为二维的表结构,例如MySQLOracle 中的表结构数据

    • 优点:方便管理,方便查询
    • 缺点:扩张结构较难
  • 非结构化数据,无法用二维表表示的数据,例如服务器日志、通讯记录、工作文档、报表等,这些数据维度管,数据量大,数据的存储、查询成本大,往往需要专业的人员和统计模型进行处理,通常会将这些数据保存到 NoSQL 数据库中去,例如 RedisMongoDB,通常是以 key - value 键值对

    • 优点:查询快
    • 缺点:由于他们的非特征性和歧义性,会更难理解
  • 半结构化数据,将数据结构和内容混在一起,没有明显的区分,例如存储员工的简历,通常装载在XMLHtml等中 ,保存在 MongoDBRedisHBase

    • 优点:能够灵活的扩展
    • 缺点:查询内容不易

如何快速、准确地查询结构化数据、非结构化数据当中的内容,ElasticSearch 就是为此诞生的

一、索引

索引创建之后是不允许被修改的,只能被删除

查询

1
2
3
4
5
## 查看 es 中的所有索引
GET /_cat/indices

## 查看 es 中的所有索引,包含标题
GET /_cat/indices?v

创建

1
2
3
4
5
6
7
8
9
10
11
## 创建索引
PUT /索引名

## 创建索引,并设置属性
PUT /索引名
{
"settings": {
"number_of_shards": 1, ## 指定主分片的数量
"number_of_replicas": 0 ## 指定副本分片的数量
}
}

删除

1
DELETE /索引名

二、映射

  • 字符串类型:keyword、text
  • 数字类型:integer、long
  • 小数类型:float、double
  • 布尔类型:boolean
  • 日期类型:date

创建

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
## 创建商品索引 products 指定 mapping {
id,
title,
price,
created_at,
description
}
PUT /products
{
"settings": {
"number_of_shards": 1, ## 指定主分片的数量
"number_of_replicas": 0 ## 指定副本分片的数量
},
"mappings": {
"properties": {
"id": {
"type": "integer"
},
"title": {
"type": "keyword"
},
"price": {
"type": "double"
},
"created_at": {
"type": "date"
},
"description": {
"type": "text"
}
}
}
}

查看

1
GET /索引名/_mapping

三、文档

创建

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
POST /索引名/_doc/id ## 指定文档 id
如:

POST /products/_doc/1
{
"title": "iphone13",
"price": 8999.9,
"created_at": "2021-09-15",
"description": "xxxxxxx"
}

POST /索引名/_doc ## 不指定文档 id,那么内部将会自动分配一个 uuid
如:

POST /products/_doc/1
{
"title": "iphone13",
"price": 8999.9,
"created_at": "2021-09-15",
"description": "xxxxxxx"
}

查询

1
GET /索引名/_doc/id

删除

1
DELETE /索引名/_doc/id

更新

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 第一种方式
PUT /索引名/_doc/id
如:
PUT /products/doc/1 ## 先删除,再插入。可能会导致原来存有的映射丢失
{
"title": "iphone14"
}

# 第二种方式
POST /索引名/_doc/id/_update
{
"doc": {

}
}
如:
POST /products/_doc/1/_update
{
"doc": {
"title": "iphone14"
}
}

五、批量操作 _bulk

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 文档批量操作 _bulk
POST /索引名/_doc/_bulk
如:
POST /products/_doc/_bulk
# 特别注意:
# 一、批操作不能回车换行
# 二、不是一个原子性操作,不会因为某一条有误而导致整个批操作失败

# 以下是关于 添加 更新 删除 的批操作
{"index": {"_id": 2}}
{"id": 2,"title": "日本豆","price": 1.8,"created_at": "2012-11-12","description": "好难吃的日本豆!"}
{"update":{"_id": 3}}
{"doc":{"title":"小于豆腐"}}
{"delete":{"_id":2}}

六、Query Domain Specified Language(DSL)

Query DSL 是利用 Rest API 传递 JSON 格式的请求体数据与 ES 进行交互

这种方式的查询语法让 ES 检索变得更加强大,更加简洁

语法

1
2
3
Get /索引名/_doc/_search {Json格式请求体数据}

Get /索引名/_search {Json格式请求体数据}

查询所有 [match_all]

1
2
3
4
5
6
Get /索引名/_doc/_search | Get /索引名/_search
{
"query": {
"match_all": {}
}
}

关键词查询 [term]

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
# 注意:term 基于关键词查询
# 一、查询 keyword 类型时,不会进行分词,所以要使用全部内容进行搜索
# 二、查询 text 类型时,默认 es 标准分词器对中文单字分词,对英文单词分词
# 三、查询 integerdoubledoubledate 类型时,不会进行分词
Get /索引名/_doc/_search | Get /索引名/_search
{
"query": {
"term": {
"映射名": {
"value": xxxx
}
}
}
}
如:
GET /products/_search
{
"query": {
"term": {
"price": {
"value": 49999
}
}
}
}

总结

  • ES 中除了 text 类型会进行分词,其余类型均不会分词
  • ES 中默认使用标准分词器,即对中文是单字分词,英文是单词分词

范围查询 [range]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Get /索引名/_doc/_search | Get /索引名/_search
{
"query": {
"range": {
"映射名": {

}
}
}
}
如:
GET /products/_search
{
"query": {
"range": {
"price": {
"gte": 1400,
"lte": 9999
}
}
}
}

前缀查询 [prefix]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Get /索引名/_doc/_search | Get /索引名/_search
{
"query": {
"prefix": {
"映射名": {
"value": "xxx"
}
}
}
}
如:
GET /products/_search
{
"query": {
"prefix": {
"title": {
"value": "ipho"
}
}
}
}

通配符查询 [wildcard]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Get /索引名/_doc/_search | Get /索引名/_search
# ? 用来匹配一个任意字符
# * 用来匹配多个任意字符
{
"query": {
"wildcard": {
"映射名": {
"value": "x*?"
}
}
}
}
如:
GET /products/_search
{
"query": {
"wildcard": {
"description": {
"value": "inp*"
}
}
}
}

多 id 查询 [ids]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Get /索引名/_doc/_search | Get /索引名/_search
{
"query": {
"ids": {
"values": [
"id1",
"id2"
]
}
}
}
如:
GET /products/_search
{
"query": {
"ids": {
"values": ["xxxxxx", "xxxxxxxxxx"]
}
}
}

模糊查询 [fuzzy]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 注意:最大模糊错误在 0 - 2 之间
Get /索引名/_doc/_search | Get /索引名/_search
{
"query": {
"fuzzy": {
"映射名": "xxxx"
}
}
}
如:
GET /products/_search
{
"query": {
"fuzzy": {
"description": "iphoneoooes"
}
}
}

总结

  • 搜索关键词长度小于等于 2 不允许存在模糊
  • 搜索关键词长度 3 - 5 允许存在一次模糊
  • 搜索关键词长度大于等于 5 允许存在两次模糊

布尔查询 [bool]

用来组合多个条件实现复杂查询

must:相当于 && 同时成立

should:相当于 || 成立一个就行

must_not:相当于 ! 不能满足一个

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
Get /索引名/_doc/_search | Get /索引名/_search
{
"query": {
"bool": {
"should | must | must_not": {

}
}
}
}
如:
# 查询满足 id 为 1 或 title 含有豆腐的值
GET /products/_search
{
"query": {
"bool": {
"should": [
{
"ids": {
"values": [1]
}
},
{
"term": {
"title": {
"values": "豆腐"
}
}
}
]
}
}
}

多字段查询 [multi_match]

1
2
3
4
5
6
7
8
9
10
11
12
# query 根据字段类型选择是否分词:
# 如果 fields 中含有不分词,将查询条件作为整体进行查询
# 如果 fields 中含有分词,将查询条件分词之后进行查询
Get /索引名/_doc/_search | Get /索引名/_search
{
"query": {
"multi_match": {
"query": "xxxxx",
"fields": ["映射名1", "映射名2"]
}
}
}

默认字段分词查询 [query_string]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# query 根据字段类型选择是否分词:
# 如果 fields 中含有不分词,将查询条件作为整体进行查询
# 如果 fields 中含有分词,将查询条件分词之后进行查询
Get /索引名/_doc/_search | Get /索引名/_search
{
"query": {
"query_string": {
"default_field": "映射名"
"query": "xxxxxx"
}
}
}
如:
GET /products/_search
{
"query": {
"query_string": {
"default_field": "description",
"query": "屏幕真的很不错"
}
}
}

返回指定条数 [size]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Get /索引名/_doc/_search | Get /索引名/_search
{
"query": {
...
},
"size": n
}
如:
GET /products/_search
{
"query": {
"match_all": {}
},
"size": 5
}

分页查询 [from]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Get /索引名/_doc/_search | Get /索引名/_search
{
"query": {
...
},
"from": 从第几页开始查询
"size": 每页大小
}
如:
GET /products/_search
{
"query": {
"match_all": {}
},
"from": 0
"size": 5
}

指定字段排序 [sort]

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
Get /索引名/_doc/_search | Get /索引名/_search
{
"query": {
...
},
"sort": [
{
"映射名": {
"order": "desc" ## 默认是降序
}
}
]
}
如:
GET /products/_search
{
"query": {
"match_all": {}
},
"sort": [
{
"price": {
"order": "desc"
}
}
]
}

放回指定字段 [_source]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Get /索引名/_doc/_search | Get /索引名/_search
{
"query": {
...
},
"_source": ["映射名1", "映射名2", "映射名3"]
}
如:
GET /products/_search
{
"query": {
...
},
"_source": ["id", "title", "description"]
}

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!