经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » Elasticsearch » 查看文章
ES 13 - Elasticsearch的元字段(_index、_type、_source、_routing等)
来源:cnblogs  作者:马瘦风  时间:2019/4/10 8:42:18  对本文有异议

元字段是ES为每个文档配置的内置字段, 主要用于ES内部相关操作.

1 标识元字段

1.1 _index - 文档所属的索引

_index标注document属于哪个index, 是一个虚拟字段, 不会被添加到Lucene索引中.

将类似的文档 (也就是具有相同field的文档) 存放到同一个index中, 是一种良好的数据建模思想.
提供大量查询的index, 最好不要同时提供大量的统计、聚合等操作——通过把特定的index路由到指定的shard上, 便于系统的优化.

注意: 索引名称必须是小写的字母, 不能以下划线"_"开头, 不能包含逗号 ",".

在term或者terms查询, 聚合、脚本以及排序时, 可以访问_index字段的值.

在多个索引中执行查询时, 可以通过添加查询子句来关联特定的索引文档, 使用示例——同时查询多种index:

  1. GET website,book_shop/_search
  2. {
  3. "query": {
  4. "terms": { // 查询_index是website和book_shop的文档
  5. "_index": [ "website", "book_shop"] }
  6. },
  7. "aggs": {
  8. "indices": { // 对_index字段进行聚合操作
  9. "terms": { "field": "_index", "size": 10 }
  10. }
  11. },
  12. "sort": { // 对_index字段进行排序操作
  13. "_index": { "order": "asc" }
  14. },
  15. "script_fields": { // 使用脚本, 显示_index字段
  16. "index_name": {
  17. "script": {
  18. "lang": "painless",
  19. "source": "doc['_index']"
  20. }
  21. }
  22. }
  23. }

1.2 _uid - 包含_type和_id的复合字段

_uid_type_id的组合, 形式为{type}#{id}. 可以用于查询、聚合、脚本和排序.

(1) 添加文档:

  1. PUT website/blog/4
  2. {
  3. "text": "blog with ID 4"
  4. }
  5. PUT website/blog/5?refresh=true
  6. {
  7. "text": "blog with ID 5"
  8. }

(2) 检索文档:

说明: 对_uid字段的访问API已经过期, 需要使用_id替换.

  1. #! Deprecation: Fielddata access on the _uid field is deprecated, use _id instead
  1. GET website/_search
  2. {
  3. "query": {
  4. "terms": { // 通过_uid查询_type和_id的复合字段
  5. "_uid": ["blog#4", "blog#5"]
  6. }
  7. },
  8. "aggs": {
  9. "uid_aggs": {
  10. "terms": { // 这里通过_uid聚合的操作已经过期
  11. "field": "_id", "size": 10
  12. }
  13. }
  14. },
  15. "sort": { // 这里通过_uid排序的操作已经过期
  16. "_id": { "order": "desc"}
  17. },
  18. "script_fields": {
  19. "uid_script": {
  20. "script": { // 这里对_uid的脚本操作已经过期
  21. "lang": "painless",
  22. "source": "doc['_id']"
  23. }
  24. }
  25. }
  26. }

1.3 _type - 文档的类型

_type元字段用来标注document属于哪个类型, 也被称作映射类型.

注意: type的名称可以是大写或小写字母, 但不能以下划线"_"开头, 不能包含逗号",".

在Elasticsearch 6.0之前的版本中, 一个index可能会被划分为多个type, 例如: 商品中有电子商品, 服装商品, 生鲜商品...

在Elasticsearch 6.0之后, 一个index只能包含一个type, 否则将出现错误.

每一个索引文档都包含_type_id字段, _type字段的目的是通过类型名加快搜索速度.

_type字段可以在查询、聚合、排序以及脚本中访问到.

关于type的底层数据结构, 可参见ES XX - Elasticsearch对索引类型(_type)的处理方式.

1.4 _id - 文档的id

_id代表document的唯一标识, 与_index_type一起, 唯一标识和定位一个document.

注意: 可以手动指定document的id(PUT index/type/id), 也可以不指定, Elasticsearch在添加文档时会自动为其创建id.

可以在查询、脚本中访问, 查询示例:

  1. GET website/_search
  2. {
  3. "query": {
  4. "terms": {"_id" : ["1", "2"]}
  5. },
  6. "aggs": {
  7. "id_aggs": {
  8. "terms": {
  9. "field": "_id", "size": 10
  10. }
  11. }
  12. },
  13. "script_fields": {
  14. "id_script": {
  15. "script": {
  16. "lang": "painless",
  17. "source": "doc['_id']"
  18. }
  19. }
  20. }
  21. }

2 文档来源元字段

2.1 _source - 文档原始JSON内容

文档的原始JSON内容将索引到_source字段中, 该字段本身不建立索引, 但是会被存储.

搜索文档时默认返回该字段及其内容, 但无法用于搜索.

2.1.1 关闭_source功能

_source功能默认是开启的, 它会产生额外的存储开销, 可以关闭:

  1. PUT website
  2. {
  3. "mappings": {
  4. "blog": {
  5. "_source": {"enabled": false}
  6. }
  7. }
  8. }
  9. // 或者:
  10. PUT website/_mapping/blog
  11. {
  12. "_source": {"enabled": false}
  13. }

注意: 必须在创建索引时关闭, 创建之后不允许修改, 否则将会发生如下错误:

  1. {
  2. "error": {
  3. "root_cause": [
  4. {
  5. "type": "resource_already_exists_exception",
  6. "reason": "index [website/zIUdhInBQsOUi_4Tt2SSkQ] already exists",
  7. "index_uuid": "zIUdhInBQsOUi_4Tt2SSkQ",
  8. "index": "website"
  9. }
  10. ],
  11. "type": "resource_already_exists_exception",
  12. "reason": "index [website/zIUdhInBQsOUi_4Tt2SSkQ] already exists",
  13. "index_uuid": "zIUdhInBQsOUi_4Tt2SSkQ",
  14. "index": "website"
  15. },
  16. "status": 400
  17. }

2.1.2 查询时指定返回字段

_source功能被禁止, 将造成大量功能无法使用:

partial update 功能基于_source实现;
hilight 高亮显示功能基于_source实现;
reindex 重建索引功能基于_source实现, 不需要从其他外部存储中获取数据, 再index;
基于_source定制返回field;
调试query时更容易, 因为可以很直观地看到_source内容……

可以在创建index时, 在mapping中通过includes/excludes参数来减少_source字段的内容:

  1. PUT logs
  2. {
  3. "mappings": {
  4. "event": {
  5. "_source": {
  6. "includes": ["*.count", "meta.*"], // 包含的字段
  7. "excludes": ["meta.desc", "meta.other.*"] // 不包含的字段
  8. }
  9. }
  10. }
  11. }

移除的字段不会被存储在_source中, 但仍然可以搜索到这些字段.

可以在检索时, 禁止返回原始内容:

  1. GET website/blog/1?_source=false

如果只想获取_source的部分内容, 可以使用_source_includes_source_excludes参数:

  1. GET website/blog/1?_source_includes=title,content
  2. GET website/blog/1?_source_excludes=post_date,author_id

Elasticsearch 6.0之前的版本中: 使用_source_include_source_exclude用来指定检索的结果中是否包含_source中的某个字段;
Elasticsearch 6.0之后的版本中: 相关的API修改为: _source_includes_source_excludes——多加了s.

2.2 _size - _source字段占用的字节数

记录_source字段占用的字节数, 由插件mapper-size提供.

3 索引元字段

3.1 _all - 文档所有字段的值

(1) ES 6.0之后的方法:

在Elasticsearch 6.0版本中, _all字段已经被禁用了. 若要开启, 官方建议是:

"Enabling [_all] is disabled in 6.0. As a replacement, you can use [copy_to] on mapping fields to create your own catch all field."
——大致意思是: _all已经不允许使用了, 作为替换, 我们可以使用copy_to关键字来创建需要获取的所有字段的内容.

copy_to的使用方法如下:

  1. PUT logs
  2. {
  3. "mappings": {
  4. "event": {
  5. "properties": {
  6. "event_id": {
  7. "type": "text",
  8. "copy_to": {"enabled": true}
  9. },
  10. "event_desc": {
  11. "type": "text",
  12. "copy_to": {"enabled": true},
  13. "analyzer": "english"
  14. },
  15. "time": {
  16. "type": "date",
  17. "copy_to": {"enabled": true},
  18. "format": "strict_date_optional_time||epoch_millis"
  19. }
  20. }
  21. }
  22. }
  23. }

(2) ES 6.0以前的方法:

在Elasticsearch 6.0之前, _all字段的使用方式如下:

_all字段包含1个文档的全部field的内容: 用一个大字符串关联其他所有字段的值, 用空格作为分隔符.
_all字段可以被分析和索引, 但不会被存储 —— 默认的搜索field.
通过_all字段可以对文档的值进行搜索而不必知道相关的字段名.
_all字段丢失了长字段(低相关性)和短字段(高相关性)之间的区别 —— 在相关性搜索要求比较高的时候, 应该明确指出要查询的字段.

① **_all字段需要额外的处理器周期, 且耗费更多的磁盘空间, 若不需要, 建议禁用此功能:**

  1. PUT website/_mapping/blog
  2. {
  3. "_all": {"enabled": false}
  4. }

② 或 在field中设置include_in_all —— 是否要将field的值包含在_all中:

  1. PUT website/_mapping/blog
  2. {
  3. "properties": {
  4. "test_field": {
  5. "type": "text",
  6. "include_in_all": false
  7. }
  8. }
  9. }

3.2 _field_names - 文档所有非空字段名

该字段可以用在查询、聚合以及脚本中 —— 用于查找指定字段的值非空的文档是否存在.

使用示例:

  1. GET website/_search
  2. {
  3. "query": {
  4. "terms": {"_field_names": ["content"]}
  5. }
  6. }

4 路由元字段

4.1 [过期]_parent - 在type间创建父子关系

(1) 创建映射:

  1. PUT store
  2. {
  3. "mappings": {
  4. "book": {},
  5. "it_book": {
  6. "_parent": {"type": "book"} // 指定其父类
  7. }
  8. }
  9. }

(2) 插入父文档:

  1. PUT store/book/1
  2. { "desc": "this is parent book"}

(3) 插入子文档, 并指出其父文档:

  1. PUT store/it_book/2?parent=1
  2. { "desc": "this is child it_book"}

(4) 父子文档的限制:

① 父type和子type必须不同.
② _parent的type的值只能是不存在的类型 —— 一个type被创建后就不能称为父类型了.

(5) 其他说明:

父子文档必须索引在同一个分片上:
① parent的编号用于子文档的路由值, 确保子文档被索引到父文档所在的分片中.
② 查询、更新、删除子文档时, 也需要提供相同的parent值.

4.2 _routing - 自定义的路由值

用于将文档路由到指定的分片上. 通过如下公式将文档路由到特定的分片:

shard_num = hash(_routing) % num_primary_shards

如果不指定_routing的值, 默认使用文档的_id字段. 如果存在父文档则使用其_parent的编号.

可以通过为某些文档都指定相同的路由值, 来实现对这些文档的自定义路由功能:

  1. // 此文档使用'user_5220'作为其路由值, 在查询、更新、删除时同样需要提供此路由值
  2. PUT website/blog/1?routing=user_5220
  3. {
  4. "title": "xxx"
  5. }

_routing字段可以在查询、聚合、脚本以及排序的时候访问. 比如直接指定路由值来搜索相关的文档:

  1. GET website/_search
  2. {
  3. "query": {
  4. "terms": {"_routing": [ "user_5220" ] }
  5. }
  6. }

5 其他元字段

_meta - 应用特定的元字段: 每个type都可以拥有自定义的元数据 —— ES并不会使用, 但可以用来存储应用程序的特定信息.

使用示例:

  1. PUT website
  2. {
  3. "mappings": {
  4. "user": {
  5. "_meta": {
  6. "class": "com.healchow.website.pojo.User",
  7. "version": {"min": "1.0", "max": "1.3"}
  8. }
  9. }
  10. }
  11. }

参考资料

Elasticsearch官方文档 - Meta-Fields

版权声明

作者: ma_shoufeng(马瘦风)

出处: 博客园 马瘦风的博客

您的支持是对博主的极大鼓励, 感谢您的阅读.

本文版权归博主所有, 欢迎转载, 但请保留此段声明, 并在文章页面明显位置给出原文链接, 否则博主保留追究相关人员法律责任的权利.

原文链接:http://www.cnblogs.com/shoufeng/p/10679725.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号