写在前面
本文看下es数据建模相关的内容。
1:什么是数据建模
数据建模是对真实数据的一种抽象,最终映射为计算机形式的表现。其包括如下三个阶段:
1:概念模型
2:逻辑模型
3:数据模型
2:es数据建模的过程
es的数据建模其实就是确定各个字段都需要如何进行设置,什么类型?是否需要搜索?等,具体需要考虑的问题如下:
注意以上四个要素没有先后的顺序,而只是需要综合考虑的因素。
2.1:数据类型
为了选择合适的数据类型,我们来看下每种数据类型的特点。
2.1.1:text
默认会被分词器分词,可以搜索,但是不支持聚合和排序,如果想要支持的话需要显式将fielddata设置为true。
2.1.2:keyword
不会被分词,所以一般用在不需要分词时使用,如主键id,邮箱,手机号,身份证号等。支持聚合,搜索和排序,以及用于查询时精确匹配方式的过滤。
2.1.3:多字段类型
当希望一个数据按照多种的数据类型来存储,从而满足诸如按照不同的分词器进行分词,按照不同的查询条件进行查询(如存储为int则可以按照range来查询),但又不希望设置多个字段时使用。默认的在es中如果时字段时text类型的,则会默认添加一个名称为keyword的keyword类型的字段,当然实际工作中我们我们不需要这个默认行为则可以通过显式mapping来自己定义。
2.1.4:数值类型
数值类型是一种结构化数据,数值类型应该尽量设置能够满足存储要求的最小类型,如可以设置为byte,就不要设置为long。
2.1.5:枚举类型
枚举类型是一种结构化数据,建议设置为keyword,以获得更好的性能。
2.1.6:日期,布尔,地理信息等
设置为对应的类型即可。
2.2:搜索,聚合,排序
- 搜索
是否需要被搜索,也是对字段进行建模时要考虑的一个重要因素,因为搜索功能需要分词,以及创建对应的倒排索引数据结构,所以需要额外的存储消耗,以及构建对应数据结构的性能消耗。 - 聚合,排序
聚合和排序功能需要依赖于doc_values,和fielddata,需要简历对应的数据结构来满足聚合和排序功能,因此也会有对应的存储成本,和对应数据结构的维护成本。
对于这三个因素可从以下方面进行考虑:
1:如果是同时不需要搜索,聚合和排序,则可考虑设置enable=false,不存储_source(还需要注意不存储_source的话将无法reindex和更新)
2:如果是不需要搜索,则可以设置index:false
3:如果不需要聚合和排序,则可以设置doc_values和fielddata为false
4:如果是更新频繁,聚合频繁,则可考虑设置keyword类型的eager_global_ordinals为true,可以利用缓存来提高性能。
2.3:额外存储字段值
如果希望额外存储字段值,则可以设置store:true,一般结合enbled:false使用。
enabled:false一般应用在一些指标数据的存储上,这些数据不需要reindex,更新。此时如果还希望查看某些字段的话则可以设置store为true。
但是实际的应用中不建议直接设置enabled:false,而是考虑使用高压缩的存储方式来减少存储的开销。
2.4:数据建模优化实例
假定我们要对如下的数据进行建模:
如下是默认生成的mapping:
其中cover_url
被自动映射为text类型,并增加keyword类型的子字段,如下:
# Index 一本书的信息
PUT books/_doc/1
{"title": "Mastering ElasticSearch 5.0","description": "Master the searching, indexing, and aggregation features in ElasticSearch Improve users’ search experience with Elasticsearch’s functionalities and develop your own Elasticsearch plugins","author": "Bharvi Dixit","public_date": "2017","cover_url": "https://images-na.ssl-images-amazon.com/images/I/51OeaMFxcML.jpg"
}#查询自动创建的Mapping
GET books/_mapping
假定根据实际的业务需求,cover url不需要支持搜索,只需要支持聚合即可,此时我们就可以将其显式的设置为keyword,并将index设置为false,如下:
DELETE books#优化字段类型
PUT books
{"mappings": {"properties": {"author": {"type": "keyword"},"cover_url": {"type": "keyword","index": false},"description": {"type": "text"},"public_date": {"type": "date"},"title": {"type": "text","fields": {"keyword": {"type": "keyword","ignore_above": 100}}}}}
}GET books/_mapping
此时cover_url因为设置了index:false就不支持搜索了:
#Cover URL index 设置成false,无法对该字段进行搜索
POST books/_search
{"query": {"term": {"cover_url": {"value": "https://images-na.ssl-images-amazon.com/images/I/51OeaMFxcML.jpg"}}}
}
但依然是支持聚合的:
#Cover URL index 设置成false,依然支持聚合分析
POST books/_search
{"aggs": {"cover": {"terms": {"field": "cover_url","size": 10}}}
}
假定需求发生变更,要求将文章的内容存储在content字段中,并且不需要做更新和reindex。
考虑到content内容比较大,所以如果放在_source中返回的话会占用比较多的网络带宽资源,并且数据查询到额速度也会降低,所以为了解决这个问题,我们可以考虑如下的两种方案:
1:source filtering不返回数据,特别是content
2:设置enabled:false,并设置字段store:true
其中对于1:source_fitering 只是在返回给客户端时不返回,在汇总数据时还是返回的,如下图:
所以对于这个需求我们需要通过2设置enabled:false来解决。
如下在mapping中显式设置enabled:false:
DELETE books
#新增 Content字段。数据量很大。选择将Source 关闭
PUT books
{"mappings": {"_source": {"enabled": false},"properties": {"author": {"type": "keyword","store": true},"cover_url": {"type": "keyword","index": false,"store": true},"description": {"type": "text","store": true},"content": {"type": "text","store": true},"public_date": {"type": "date","store": true},"title": {"type": "text","fields": {"keyword": {"type": "keyword","ignore_above": 100}},"store": true}}}
}
插入数据:
# Index 一本书的信息,包含Content
PUT books/_doc/1
{"title": "Mastering ElasticSearch 5.0","description": "Master the searching, indexing, and aggregation features in ElasticSearch Improve users’ search experience with Elasticsearch’s functionalities and develop your own Elasticsearch plugins","content": "The content of the book......Indexing data, aggregation, searching. something else. something in the way............","author": "Bharvi Dixit","public_date": "2017","cover_url": "https://images-na.ssl-images-amazon.com/images/I/51OeaMFxcML.jpg"
}#查询结果中,Source不包含数据
POST books/_search
{}
但依然可以查询和高亮,因为store:true所以会存储字段的原始值(但是enabled:false所以原始文档是不存储的,即_source是没有信息的)
:
#搜索,通过store 字段显示数据,同时高亮显示 conent的内容
POST books/_search
{"stored_fields": ["title","author","public_date"],"query": {"match": {"content": "searching"}},"highlight": {"fields": {"content": {}}}
}
写在后面
参考文章列表
source filtering 。