概要
前两天学习 Elasticsearch 的时候,我跳过了 mapping
部分,直接录入数据后查询,当时遗留了一些疑问,这篇文章正好学习这一部分
Mapping 是什么?
在创建索引后,可以手动创建索引的 mapping,也可以直接提交数据,Elasticsearch 会自动创建 mapping(dynamic mapping)
mapping 中定义了我们数据中各个字段的类型,以及这个字段如何分词等相关属性。
这里查看一下之前文章录入数据时 Elasticsearch 自动创建的 mapping
curl -X GET "localhost:9200/books_idx/_mapping?pretty"
返回数据
{
"books_idx" : {
"mappings" : {
"properties" : {
"author" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"isbn" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"name" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"pubdate" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
},
"fielddata" : true
},
"publish" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
},
"fielddata" : true
}
}
}
}
}
Ps:忽略 fielddata 字段,那是后来手动修改的属性
比如数据中的 author 字段,Elasticsearch把它设置为 text
类型,并且为它添加了属性,属性名称叫 keyword, 这个 keyword 属性类型是 keyword
类型,设置 ignore_above 属性值为 256,即如果数据内容长度超过这一设置,将不会被索引或存储
"author" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
那么 text
和 keyword
有什么区别呢,Elasticsearch 会把 text
类型进行分词存储,便于全文检索等功能,而如果是 keyword
类型,那么这个字段不会被分词,搜索时用于精确搜索,可以用于排序和聚集
字段多类型
很多时候,我们的数据内容可能即需要精确的查找,又想让这个字段支持模糊搜索,那就需要设置这个字段为多个类型,Elasticsearch 在自动创建 mapping 的时候已经是这么做的了
使用方法就是,如果想要在这个字段上模糊搜索,就使用 author,如果想要精确查找某个作者,就使用 author.keyword
到这里,已经解决了上篇文章结尾遗留的问题,稍后就那个小的遗留问题进行补充
Elasticsearch 类型
现在再看一下 Elasticsearch 支持的基础类型
序号 | 类型 | 简要描述 |
---|---|---|
1 | text |
自动分词,用于模糊搜索等功能 |
2 | keyword |
用于精确查找、排序、聚合操作等 |
3 | date |
录入指定格式的数据,能够进行排序转换等,详见:date |
4 | integer |
32位整数,还有:long short byte double float 等,详见:number |
6 | boolean |
可以在搜索时用于判断文档状态,或用于脚本,详见:boolean |
7 | ip |
可以存储 IPv4 或者 IPv6 类型的地址,可用子网掩码进行搜索,详见:ip |
除了基础类型,还有关于层级的类型说明,如:object
和 nested
,还有关于位置的类型,就不多描述了,用到了参考文档
另外,Field 属性里的类型可以参考Field datatypes
遗留问题
上一篇《ELK学习笔记(二)——关于 Elasticsearch 检索》遗留的小问题,现在就很明确了,因为当时查询用 publish 出版社字段来进行聚合数量统计,但是这个字段是 text
类型的,导致查询出的结果GG(部分)
"years_count" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 10,
"buckets" : [
{
"key" : "出",
"doc_count" : 6
},
{
"key" : "版",
"doc_count" : 6
},
{
"key" : "社",
"doc_count" : 5
},
{
"key" : "业",
"doc_count" : 3
}
...
}
}
现在看来很好解决,使用字段的属性 keyword 原始的字段进行聚合统计查询就可以了
curl -X GET "localhost:9200/books_idx/_doc/_search?pretty" -H 'Content-Type: application/json' -d'
{
"aggs": {
"years_count": {
"terms": { "field": "publish.keyword" }
}
}
}
'
结果如下(部分)
"aggregations" : {
"years_count" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [
{
"key" : "电子工业出版社",
"doc_count" : 2
},
{
"key" : "人民邮电出版社",
"doc_count" : 1
},
{
"key" : "作家出版社",
"doc_count" : 1
},
{
"key" : "北京联合出版公司",
"doc_count" : 1
},
{
"key" : "机械工业出版社",
"doc_count" : 1
}
]
}
}
手动创建 Mapping
只需要按照 JSON 规则,PUT 到相应名称的索引即可,前提是索引已经存在
curl -X PUT "localhost:9200/my_idx/_mapping?pretty" -H 'Content-Type: application/json' -d'
{
"properties": {
"name": {
"type": "keyword"
}
}
}
'
更新 Mapping
已经创建的 Mapping 是不能修改字段的类型的,可以添加新的字段,也可以增加字段的类型,比如原先设置了 auther 字段为 text
类型,后来想要精确查找,重新PUT一份覆盖就可以了
删除 Mapping
It is no longer possible to delete the mapping for a type. Instead you should delete the index and recreate it with the new mappings.
官方文档说不再支持删除 mapping,当你想要删除的时候,正确的做法是直接删除索引并重新创建
Mapping 的学习就先到这里,后续用到其它的知识点再进行补充
参考