1 ES 数据组织概念
ES 的数据组织概念和 MySQL 和 MongoDB 对比如下:("最受欢迎"的依据)
注意这里 ES的Index的概念类似于MySQL的数据库,在后文中容易造成混淆。
更加值得注意的是:因为如下各方面原因,在ES6之后,一个Index不在允许存在多个type,在 Elasticsearch 7版本中,已经将 type 去掉了,但是为了兼容老格式,会将 _doc 或自己命名的type作为一个唯一的 type,8.x将彻底不支持type。
-
我们经常把二维数据库与ES作类比的方式是不正确的假设。把“index”类比为数据库,“type”类比为表。具体原因是,数据库的表是物理独立的,一个表的列跟另外一张表相同名称的列没有关系,而ES中并非如此,不同type映射类型中具有相同名称的字段在内部由相同的Lucene字段支持。
-
当您想要索引一个deleted字段在不同的type中数据类型不一样。一个类型中为日期字段,另外一个类型中为布尔字段时,这可能会导致ES的存储失败,因为这影响了ES的初衷设计。
-
另外,在一个index中建立很多实体,type,没有相同的字段,会导致数据稀疏,最终结果是干扰了Lucene有效压缩文档的能力,说白了就是影响ES的存储、检索效。
2 索引的管理
ES 的语法遵循 RESTfull 风格,PATH的资源结构为 /[index]/[type]/[document]
- 最简单地创建索引,会采用默认配置
PUT /index_name
- 创建索引并指定一些配置
PUT /index_name
{
"settings": { // settings
"number_of_shards": 10, // 分片数目
"number_of_replicas": 1, // 每个分片副本数目
"refresh_interval": "1s" // 数据落盘刷新频率
},
"mappings": { // mapping, 定义数据 schema,下面定义了5个字段,
"properties": { // 除了type, 每个字段有更多的属性可选,这里不展开介绍
"uid": { "type": "long" },
"phone": {"type": "long"},
"message": {"type": "keyword"},
"msgcode": {"type": "long"},
"sendtime": {"type": "date",
"format": "yyyy-MM-dd HH:mm:ss"}
}
}
}
- 索引的 mapping 是可以根据数据自动更新的,如不创建索引直接插入如下数据
POST /index_name/_doc/1
{
"first_name" : "Tim2",
"last_name" : "Wang",
"age" : 26,
"about" : "go go go golang",
"interests": [ "golang", "world peace" ],
"hasomer": "gugu"
}
推荐的做法是:事先定义好索引的Schema,也就是创建索引并制定好Mapping,并关闭 Dynamic Mapping 特性。
PUT /index_name/_mapping/data
{
"dynamic":false
}
或者
PUT /index_name/_mapping/data
{
"dynamic":"strict"
}
后者比前者的限制更为严格一些,当文档存在Mapping里没有的field时,前者仍可插入,只是不再为新字段建立索引提供搜索。后者直接不允许插入。
也可以在elasticsearch.yml
配置文件关闭 Dynamic Mapping.
action.auto_create_index: false
index.mapper.dynamic: false
- 删除索引
DELETE /index_name
- 设置索引别名
PUT /index_name/_alias/my_alias
一个索引可以有多个别名,一个别名也可以作用在多个索引上,索引别名可用于平滑迁移, 推荐项目中使用索引别名而不是直接使用索引名。
应用索引别名可以较为方便地实现平滑迁移,推荐使用。
3 数据的CRUD
3.1 插入数据
你可以使用简单的 PUT 请求去执行操作,请求须指定文档的索引名称,唯一的文档 ID,以及请求体中一个或多个键值对。
PUT /customer/_doc/1
{
"name": "John Doe"
}
这个请求(如不存在)将自动创建一个 ID 为 1 的新文档,并储存键值对,并为其建立索引。
由于这是一个新文档,返回的结果显示新创建的文档版本号为 1。
{
"_index" : "customer",
"_type" : "_doc",
"_id" : "1",
"_version" : 1,
"result" : "created",
"_shards" : {
"total" : 2,
"successful" : 2,
"failed" : 0
},
"_seq_no" : 26,
"_primary_term" : 4
}
3.2 简单查询数据
GET /customer/_doc/1
将返回这个文档本身
{
"_index" : "customer",
"_type" : "_doc",
"_id" : "1",
"_version" : 1,
"_seq_no" : 26,
"_primary_term" : 4,
"found" : true,
"_source" : {
"name": "John Doe"
}
}
3.3 搜索数据
一旦你开始在Elasticsearch
插入数据,你就可以通过_search
方式发送请求来进行搜索,如果使用匹配搜索功能,在请求体中使用 Elasticsearch Query DSL
指定搜索条件。你也可以在请求头指定要搜索的索引名称。
如下,搜索银行索引中,所有账号按照 account_number
排序
GET /bank/_search
{
"query": { "match_all": {} },
"sort": [
{ "account_number": "asc" }
]
}
默认情况会返回符合条件的前十个结果
{
"took" : 63,
"timed_out" : false,
"_shards" : {
"total" : 5,
"successful" : 5,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value": 1000,
"relation": "eq"
},
"max_score" : null,
"hits" : [ {
"_index" : "bank",
"_type" : "_doc",
"_id" : "0",
"sort": [0],
"_score" : null,
"_source" : {"account_number":0,"balance":16623,"firstname":"Bradshaw","lastname":"Mckenzie","age":29,"gender":"F","address":"244 Columbus Place","employer":"Euron","email":"bradshawmckenzie@euron.com","city":"Hobucken","state":"CO"}
}, {
"_index" : "bank",
"_type" : "_doc",
"_id" : "1",
"sort": [1],
"_score" : null,
"_source" : {"account_number":1,"balance":39225,"firstname":"Amber","lastname":"Duke","age":32,"gender":"M","address":"880 Holmes Lane","employer":"Pyrami","email":"amberduke@pyrami.com","city":"Brogan","state":"IL"}
}, ...
]
}
}