前言
前面一章节我们讲了ES的一些核心概念,这一章节我们将使用Kibana对ES做一些常规操作,比如索引库的CRUD,文档的CRUD等。喜欢的话请给个好评。
索引库index的CRUD
索引库有点像关系型数据库的database数据库,比如:对于商品数据我们可以建立一个索引库,对于订单数据库我们也可以建立一个索引库。
如果我们要把Mysql中的订单数据库存储到ES中进行检索,那么我们就应该建立一个针对订单的index索引库。而上一篇文章有说道,为了方便进行数据的扩容,ES把一个index索引中的数据切分为多个shard,分布在多台服务器上存储,默认是5个主shard,1个备shard(可自定义数量),所以创建一个索引库语法如下:
PUT orders
{
"settings":{
"number_of_shards":5,
"number_of_replicas":1
}
}
- number_of_shards : 主分片数量
- number_of_replicas :每个主分片有一个备分片
添加好索引库之后,可用通过如下命令进行查看
GET _cat/indices?v
或者查看指定的索引库
GET _cat/indices/orders
如果需要删除的话,使用 DELETE 索引库名字
即可
分词器安装
上一章有讲到ES在创建索引的时候会对采集到的数据进行分词,然后最终形成倒排索引,分词器对分词非常重要,对于英文的内容使用空格即可分词,而中文需要有专门的中文分词器。
中文分词器很多比如:IKAnalyzer ;CJKAnalyzer二分分词 ;ChineseAnalyzer单字分词 ;PaodingAnalyzer庖丁分词器等等 ,本篇文章会演示使用最多的IKAnalyzer IK分词器。
首先需要下载分词器 : https://github.com/medcl/elasticsearch-analysis-ik/releases?after=v6.3.2,我选择的版本是 elasticsearch-analysis-ik-6.8.6.zip
。
把下载好的分词器解压到 es安装目录的plugins目录即可,我在plugins目录中创建了一个ik目录,解压后如下
配置扩展词典
通过配置文件 config/IKAnalyzer.cfg.xml 可以配置词典和停词,内容如下
这里可以指定扩展词典,以及配置停词词典,也可以支持远程方式配置。扩展词典的意义在于分词的时候把某些不是单词的词作为一个单词,方便搜索,比如:阿里巴巴不是一个词语,我们希望ES把它当成一个词语就可以通过扩展词典进行配置。停词的意义在于把哪些低频搜索的词忽略掉,不参与倒排索引的创建。比如:“是”,“了”,“吗”等这种字对搜索没有帮助,可以作为停词忽略掉,还能节约索引空间。
- ext_dic :指的是扩展词典,上面的配置中表示会引用一个my_ext_dic.txt这样的扩展词典文件
- ext_stopwords:配置停词词典
- remote_ext_dic : 配置远程扩展词典,如:http://192.168.1.11/xxx.txt
remote_ext_stopwords : 配置远程停词词典
上面的配置中在 ext_dic 项配置了一个my_ext_dic.txt这样的扩展词典文件,所以需要在IKAnalyzer.cfg.xml同级目录创建该文件,内容如下
最后我们来测试一下分词器,使用kibana执行下面代码POST _analyze { "analyzer":"ik_smart", "text":"阿里巴巴和爸爸中国驻洛杉矶领事馆遭亚裔男子枪击 嫌犯已自首" }
ik_smart 代表使用的是IK分词器去对text的内容进行分词, 效果如下
除了使用 ik_smart 也可以使用 ik_max_word ,否则在分词会分得更细一点 。到这分词器安装成功,以后我们要指定使用IK分词器就指定 "analyzer":"ik_smart", 或者 "analyzer":"ik_max_word "即可
文档映射
ES的文档映射(mapping)机制用于进行字段类型确认
,将每个字段匹配为一种确定的数据类型,也就是说我们存储到ES中的数据到底用什么类型去存储。就如同Mysql创建表时候指定的每个column列的类型。 为了方便字段的检索,我们会指定存储在ES中的字段是否进行分词,但是有些字段类型可以分词,有些字段类型不可以分词,所以对于字段的类型需要我们自己去指定。 所以我们的ES的操作流程应该是 1.创建索引 -> 2.创建映射 -> 3.添加数据
我们可以通过GET {indexName}/_mapping/{typeName}
查看索引映射配置:
这里的 mappings :{} 是空的,因为我们并没有为orders这个索引指定映射。
ES中的数据类型
- 字符串 :常用的类型有 text(分词) ;keyword(不分词) ;如果某个字段被指定为text那么这个字段的值就会被分词然后创建倒排索引。 如果是keyword也会创建倒排索引,只不过是把字段的值作为整体形成倒排索引,不会分词。
- 数字 : 数字和Java差不多,有 long ; integer ; short ; double ; float
- 日期 : date
- 逻辑 : boolean
- 对象类型 : object
- 数组类型 : array
- 地理位置 : geo_point,geo_shape
需要注意的是:ES在没有配置Mapping的情况下新增文档,ES会尝试对字段类型进行猜测,并动态生成字段和类型的映射关系。比如遇到 123 数字可能会使用 long 类型存储,如下:
内容 | 默认映射类型 |
---|---|
JSON type | Field type |
Boolean: true or false | "boolean" |
Whole number: 123 | "long" |
Floating point: 123.45 | "double" |
String, valid date:"2014-09-15" | "date" |
String: "foo bar" | "string" |
创建简单映射
我们来看一下创建映射的语法格式
PUT index/_doc/_mapping
{
"_doc": {
"properties": {
"字段": {
"type": "类型"
},
"字段": {
"type": "类型"
}
}
}
}
下面来做一个案例,比如我们已经创建了一个索引库 orders (订单) ,该索引库中将要存储的订单数据库的字段有:id , title , amount , count 那么我们可以做如下映射
PUT orders/_doc/_mapping
{
"_doc": {
"properties": {
"id": {
"type": "long"
},
"title": {
"type": "text",
"analyzer": "ik_smart",
"search_analyzer": "ik_smart"
},
"amount":{
"type": "double"
},
"count":{
"type": "integer"
}
}
}
}
解释一下:这里的 _doc 指的是文档的逻辑分类 type ,可以任意指定,在ES7中取消了该逻辑分类,可以统一指定为"_doc" , id 使用long类型 ,title使用text类型(分词且索引),并指定了IK分词器(创建倒排索引时分词),amount使用double ,count使用 integer类型。
创建好之后我们通过 GET orders/_mapping
查看映射
上面是一个简单的文档映射,下面还列出了一些在做映射时可以指定的配置项
字段映射的常用属性配置列表 - 即给某个字段执行类的时候可以指定以下属性
type | 类型:基本数据类型,integer,long,date,boolean,keyword,text... |
---|---|
enable | 是否启用:默认为true。 false:不能索引、不能搜索过滤,仅在_source中存储 |
boost | 权重提升倍数:用于查询时加权计算最终的得分。 |
format | 格式:一般用于指定日期格式,如 yyyy-MM-dd HH:mm:ss.SSS |
ignore_above | 长度限制:长度大于该值的字符串将不会被索引和存储。 |
ignore_malformed | 转换错误忽略:true代表当格式转换错误时,忽略该值,被忽略后不会被存储和索引。 |
include_in_all | 是否将该字段值组合到_all中。 |
null_value | 默认控制替换值。如空字符串替换为”NULL”,空数字替换为-1 |
store | 是否存储:默认为false。true意义不大,因为_source中已有数据 |
index | 索引模式:analyzed (索引并分词,text默认模式), not_analyzed (索引不分词,keyword默认模式),no(不索引) |
analyzer | 索引分词器:索引创建时使用的分词器,如ik_smart,ik_max_word,standard |
search_analyzer | 搜索分词器:搜索该字段的值时,传入的查询内容的分词器。 |
fields | 多字段索引:当对该字段需要使用多种索引模式时使用。 |
如:城市搜索
"city":"city":{
"type": "text",
"analyzer": "ik_smart",
"fields": {
"raw": {
"type": "keyword"
}
}
}
解释:相当于给 city取了一个别名 city.raw,city的类型为text , city.raw的类型keyword
搜索 city分词 ;搜索city.raw 不分词那么以后搜索过滤和排序就可以使用city.raw字段名
如果是嵌套对象的映射的话一样嵌套即可,比如有如下对象嵌套
{
"id" : 1,
"girl" : {
"name" : "王小花",
"age" : 22
}
}
那么映射应该指定为如下
...省略...
{
//对象
"properties": {
"id": {
"type": "long"},
"girl": {
//嵌套的对象
"properties":{
"name": {
"type": "keyword"},
"age": {
"type": "integer"}
}
}
}
}
如果是数组或者对象数组,那就按照一个元素进行映射即可,比如有如下对象数组
{
"id" : 1,
"girl":[{
"name":"林志玲","age":32},{
"name":"赵丽颖","age":22}] //对象数组
}
应该做如下映射
...省略...
"properties": {
"id": {
"type": "long"
},
"girl": {
"properties": {
"age": {
"type": "long" },
"name": {
"type": "text" }
}
}
}
文档的CRUD
数据是以Docuement进行存储,通常一行数据就是一个Document,比如:一个订单数据就是一个Document,多个订单就会形成多个Document存储在index索引库中。而 type是对Document的一个逻辑分类,同一个type下的document拥有相同的列。只不过我们使用Kibana添加文档数据不需要关系Document是如何创建的,只需要通过Rest API 操作即可。
添加文档
语法 PUT index/type/id
: index是索引库 ,type是类型 ,id是文档的ID 。添加一个订单数据演示如下
数据是以JSON格式提交给ES的,ES会自己把数据创建文档,写入索引库中。图的右边是执行结果,有几个东西需要解释一下:_version 版本号是用作乐观锁,数据被修改一次version会+1 ;只不过在高版本ES中使用 _seq_no和_primary_term来代替version处理并发问题。不了解乐观锁的自行百度一下。
额外提示一下:文档的ID如果不指定的话ES会自动生成一个不重复的ID值,这种方式不推荐使用,一般还是需要手动指定文档ID。
获取文档
语法 GET index/type/id
删除文档
语法 DELETE index/type/id
修改文档
全量修改:全量修改文档和添加文档的语法一样 ,只要ID已经存在,那么添加就会变成修改,当时要注意,之所以叫全量修改是如果已有的数据是 4个列,而修改的数据只给了3个列,那么最终的数据就只有3个列。
局部修改:只是修改指定的列,其他列不动,语法:
POST /index/type/id/_update
{
"doc":{
"列" : 值,
"列": "值"
}
}
比如把订单的价格由 100 修改为200,演示如下
POST orders/_doc/1/_update
{
"doc":{
"amount":200.00
}
}