- 一、Elasticsearch
- 1. 基本概念
- 1.1 Index(索引)
- 1.2 Type(类型)
- 1.3 Document(文档)
- 1.4 倒排索引机制
- 2. 相关命令
- 2.1 _cat
- 2.2 索引一个文档(保存一条记录)
- 2.3 查询文档
- 2.4 更新文档
- 2.5 删除文档和索引
- 2.6 bulk批量API
- 3. 进阶检索
- 3.1 ES中的两种检索方法
- 3.2 Query DSL
- 3.2.1 基本语法结构
- 3.2.2 针对某个字段结构
- 3.2.3 返回部分字段
- 3.2.4 match查询
- 3.2.5 match_phrase短语匹配
- 3.2.6 multi_match多字段匹配
- 3.2.7 bool复合查询
- 3.2.8 term
- 4. aggregations聚合功能
- 4.1 基本概念
- 4.2 基本语法
- 4.3 举例
- 5.Mapping映射
- 5.1 基本概念
- 5.2 相关操作
- 5.2.1 创建映射规则
- 5.2.2 添加新字段映射
- 5.2.3 映射的更新
- 5.2.4 数据迁移
全文搜索属于最常见的需求,开源的Elasticsearch是目前全文搜索引擎的首选。它可以快速地储存、搜索和分析海量数据。Elastic的底层是开源库Lucene。但是,Lucene无法直接使用,必须自己写代码去调用它的接口。而Elastic是Lucene的封装,提供了RESTAPI的操作接口,开箱即用。
1. 基本概念 1.1 Index(索引)- 动词,相当于MySQL中的insert。ES中的索引一条数据等同于MySQL中插入一条数据。
- 名词,相当于MySQL中的Database。ES中的简历一个索引等同于MySQL中建立一个数据库。
- 在Index(索引)中,可以定义一个或多个类型。
- 类型就类似于MySQL中的Table每一种类型的数据放在一起。
- 保存在某个索引(Index)下,某种类型(Type)的一个数据(Document)。
- 文档是JSON格式的,Document就像是MySQL中的某个Table里面的内容,一条文档就类似于MySQL中的一条数据。
| 命令 | 功能 |
|---|---|
| GET请求_cat/nodes | 查看所有节点 |
| GET请求_cat/health | 查看 es 健康状况 |
| GET请求_cat/master | 查看主节点 |
| GET请求_cat/indices | 查看所有索引 |
需要具体指明保存在哪个索引的哪个类型下,可能要指明用哪个唯一标识。
//比如在customer索引下的external类型下保存1号数据:
//1.以PUT方式或POST方式发送如下请求
customer/external/1
//2.请求体内容如下
{
"name": "John Doe"
}
1.PUT和POST都可以完成文档的索引(即数据的插入)。
2.POST,如果不指定id,会自动生成id并新增数据;指定id如果id不存在就会新增这条数据,存在则会修改这个数据,并新增版本号。
3.PUT,PUT必须指定id,如果id不存在则为新增,存在则为修改。一般用PUT做修改操作。
需要指明查询哪个索引的哪个类型下的哪个文档
//比如查询customer索引下的external类型下的1号数据:
//1.以GET方式发送如下请求:
customer/external/1
//2.查询结果如下:
{
"_index": "customer", //在哪个索引
"_type": "external", //在哪个类型
"_id": "1", //记录 id
"_version": 2, //版本号
"_seq_no": 1, //并发控制字段,每次更新就会+1,用来做乐观锁
"_primary_term": 1, //同上,主分片重新分配,如重启,就会变化
"found": true, "_source": { //真正的内容
"name": "John Doe"
}
}
//3.如何实现乐观锁?
更新时,发送的请求后面携带"?if_seq_no=最新信息&if_primary_term=1"即可
2.4 更新文档
1.方式一:POST方式带_update
//比如更新customer索引下的external类型下的1号数据
//POST方式发送请求customer/external/1/_update
{
"doc":{
"name": "John Doew"
}
}
//该方式会对比源文档数据,如果相同不会进行任何操作,版本号等信息都不变。
2.方式二
//比如更新customer索引下的external类型下的1号数据
//POST方式发送请求customer/external/1
{
"name": "John Doe2"
}
//该方式就是不论数据是否不变,都会直接更新
3.方式三
//比如更新customer索引下的external类型下的1号数据
//PUT方式发送请求customer/external/1
{
"name": "John Doe2"
}
//该方式就是不论数据是否不变,都会直接更新
4.注解:以上方式都允许更新的同时增加属性,比如
//POST方式发送请求customer/external/1/_update
{
"doc": {
"name": "Jane Doe", "age": 20
}
}
2.5 删除文档和索引
1.删除文档
//比如删除customer索引下的external类型下的1号数据 //DELETE方式发送请求customer/external/1
2.删除索引
//比如删除customer索引 //DELETE方式发送请求customer2.6 bulk批量API
//1.语法格式:以POST方式发送_bulk请求,携带以下请求体
{ action: { metadata }}
{ request body }
{ action: { metadata }}
{ request body }
1.说明:bulkAPI以此按顺序执行所有的action(动作)。如果一个单个的动作因任何原因而失败,它将继续处理它后面剩余的动作。当bulkAPI 返回时,它将提供每个动作的状态(与发送的顺序相同),所以可以检查是否一个指定的动作是不是失败了。
2.注意:可以在请求中携带对哪个索引的哪个类型进行操作,如果请求中没有携带,则需要在metadata中指明,否则会报错找不到索引。
1.检索的所有条件放在请求中
GET bank/_search?q=*&sort=account_number:asc
2.利用uri和请求体进行检索
GET bank/_search
{
"query": {
"match_all": {}
},
"sort": [
{
"account_number": { "order": "desc"
}
}
]
}
3.结果分析
took:Elasticsearch 执行搜索的时间(毫秒)。 time_out:告诉我们搜索是否超时。 _shards:告诉我们多少个分片被搜索了,以及统计了成功/失败的搜索分片。 hits:搜索结果。 hits.total:搜索结果。 hits.hits:实际的搜索结果数组(默认为前10的文档)。 sort:结果的排序 key(键)(没有则按score排序)。 score和max_score:相关性得分和最高得分(全文检索用)。3.2 Query DSL
利用uri和请求体检索时,请求体其实就是我们所说的Query DSL,他要遵循指定的规则。
3.2.1 基本语法结构1.基本语法:
{
QUERY_NAME: {
ARGUMENT: VALUE,
ARGUMENT: VALUE,
...
}
}
2.举例:
GET bank/_search
{
"query": {
"match_all": {}
}
}
3.2.2 针对某个字段结构
1.基本语法:
{
QUERY_NAME: {
FIELD_NAME: {
ARGUMENT: VALUE,
ARGUMENT: VALUE,
...
}
}
}
2.举例:
{
"query": {
"match_all": {}
},
"from": 0,
"size": 5,
"sort": [
{
"account_number": {
"order": "desc"
}
}
]
}
解释:
query定义如何查询,match_all查询类型(代表查询所有的所有),es中可以在query中组合非常多的查询类型完成复杂查询。 除了query参数之外,我们也可以传递其它的参数以改变查询结果,如 sort,size等。 from+size限定,完成分页功能。 sort 排序,多字段排序,会在前序字段相等时后续字段内部排序,否则以前序为准。3.2.3 返回部分字段
1.使用方法:在_source中以数组方式指明需要返回的字段即可。
2.举例:
{
"query": {
"match_all": {}
},
"from": 0,
"size": 5,
"_source": ["age","balance"]
}
3.2.4 match查询
1.基本语法:
{
"query":{
"match": {
"FIELD": "TEST"
}
}
}
2.举例:
//例1
{
"query": {
"match": {
"account_number": "20"
}
}
}
//例2
{
"query": {
"match": {
"address": "mill"
}
}
}
//例3
{
"query": {
"match": {
"address": "mill road"
}
}
}
3.注意:查询的属性值为基本类型时,为精确匹配;查询属性值为字符串时,为全文检索;查询属性值为字符串多个单次时,还会进行分词。最后查询得到的结果会按照相关性得分由高到低的顺序返回。
3.2.5 match_phrase短语匹配1.说明:当match检索查询的属性值为字符串多个单词时,会开启分词检索。而采用match_phrase则将要匹配的值当成一个整体单词(不分词)进行检索
2.举例:
{
"query": {
"match_phrase": {
"address": "mill road"
}
}
}
3.2.6 multi_match多字段匹配
1.说明:只要指定的属性中包含要查询的值,则该条数据就会被返回。
2.举例:
//state或者address包含mill
{
"query": {
"multi_match": {
"query": "mill",
"fields": ["state","address"]
}
}
}
3.2.7 bool复合查询
1.基本概念:bool用来做复合查询,复合语句可以合并任何其它查询语句,包括复合语句,了解这一点是很重要的。这就意味着,复合语句之间可以互相嵌套,可以表达非常复杂的逻辑。
2.说明:① must:必须达到must列举的所有条件,must会贡献相关性得分。② should:应该达到should列举的条件,如果达到会增加相关文档的评分,并不会改变查询的结果。但如果query中只有should且只有一种匹配规则,那么should的条件就会被作为默认匹配条件而去改变查询结果。③ must_not必须不是指定的情况。④ filter:和must功能一样,唯一的区别是,它不会贡献相关性得分。
3.举例:
{
"query": {
"bool": {
"must": [
{ "match": { "address": "mill" } },
{ "match": { "gender": "M" } }
],
"should": [
{"match": { "address": "lane" }}
],
"must_not": [
{"match": { "email": "baluba.com" }}
],
"filter": {
"range": {
"balance": {
"gte": 10000,
"lte": 20000
}
}
}
}
}
}
3.2.8 term
1.说明:term和match一样,用于匹配某个属性的值。一般来说,全文检索字段用match,其他非text字段匹配(即精确检索)用term。
2.举例:
{
"query": {
"bool": {
"must": [
{"term": {
"age": {
"value": "28"
}
}},
{"match": {
"address": "990 Mill Road"
}}
]
}
}
}
4. aggregations聚合功能
4.1 基本概念
4.2 基本语法
"aggs": {
"aggs_name 这次聚合的名字,方便展示在结果集中": {
"AGG_TYPE 聚合的类型(avg,term,terms)": {
聚合的具体字段
}
}
4.3 举例
1.搜索address中包含mill的所有人的年龄分布以及平均年龄,但不显示这些人的详情。
{
"query": {
"match": {
"address": "mill"
}
},
"aggs": {
"group_by_state": {
"terms": {
"field": "age"
}
},
"avg_age": {
"avg": {
"field": "age"
}
}
},
"size": 0
}
2.按照年龄聚合,并且请求这些年龄段的这些人的平均薪资。
{
"query": {
"match_all": {}
},
"aggs": {
"age_avg": {
"terms": {
"field": "age",
"size": 1000
},
"aggs": {
"banlances_avg": {
"avg": {
"field": "balance"
}
}
}
}
}
,"size": 1000
}
3.查出所有年龄分布,并且这些年龄段中M的平均薪资和F的平均薪资以及这个年龄段的总体平均薪资。
{
"query": {
"match_all": {}
},
"aggs": {
"age_agg": {
"terms": {
"field": "age",
"size": 100
},
"aggs": {
"gender_agg": {
"terms": {
"field": "gender.keyword",
"size": 100
},
"aggs": {
"balance_avg": {
"avg": {
"field": "balance"
}
}
}
},
"balance_avg":{
"avg": {
"field": "balance"
}
}
}
}
}
,
"size": 1000
}
5.Mapping映射
5.1 基本概念
映射指的就是文档中的每个属性的数据类型,在第一次存放文档时,ES就会为每个文档中的每一个属性猜测一个数据类型。
5.2 相关操作 5.2.1 创建映射规则//创建索引并指定映射
PUT /my-index
{
"mappings": {
"properties": {
"age": { "type": "integer" },
"email": { "type": "keyword" },
"name": { "type": "text" }
}
}
}
5.2.2 添加新字段映射
//在已有索引my-index中添加新属性及其映射
PUT /my-index/_mapping
{
"properties": {
"employee-id": {
"type": "keyword",
}
}
}
5.2.3 映射的更新
对于已经存在的映射字段,我们不能更新,更新必须创建新的索引进行数据迁移。
5.2.4 数据迁移首先明确,在ES6以后,开始逐步移除type(注意,此时的type代表SQL中的表,而不是属性的数据类型)
1.ES6之前的写法
POST _reindex
{
"source": {
"index": "原索引",
"type": "类型(代表SQL中的表)"
},
"dest": {
"index": "目的索引"
}
}
2.ES6之后的写法
POST _reindex
{
"source": {
"index": "原索引"
},
"dest": {
"index": "目的索引"
}
}



