zoukankan      html  css  js  c++  java
  • ES 13

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

    1 标识元字段

    1.1 _index - 文档所属的索引

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

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

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

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

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

    GET website,book_shop/_search
    {
        "query": {
            "terms": {    // 查询_index是website和book_shop的文档
                "_index": [ "website", "book_shop"] }
        },
        "aggs": {
            "indices": {  // 对_index字段进行聚合操作
                "terms": { "field": "_index", "size": 10 }
            }
        },
        "sort": {         // 对_index字段进行排序操作
            "_index": { "order": "asc" }
        },
        "script_fields": {  // 使用脚本, 显示_index字段
            "index_name": {
                "script": { 
                    "lang": "painless",
                    "source": "doc['_index']"
                }
            }
        }
    }
    

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

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

    (1) 添加文档:

    PUT website/blog/4
    {
        "text": "blog with ID 4"
    }
    
    PUT website/blog/5?refresh=true
    {
        "text": "blog with ID 5"
    }
    

    (2) 检索文档:

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

    #! Deprecation: Fielddata access on the _uid field is deprecated, use _id instead
    
    GET website/_search
    {
        "query": { 
            "terms": {       // 通过_uid查询_type和_id的复合字段
                "_uid": ["blog#4", "blog#5"]
            }
        },
        "aggs": {
            "uid_aggs": {
                "terms": {    // 这里通过_uid聚合的操作已经过期
                    "field": "_id", "size": 10
                  }
            }
        }, 
        "sort": {             // 这里通过_uid排序的操作已经过期
            "_id": { "order": "desc"}
        }, 
        "script_fields": {
            "uid_script": {
                "script": {   // 这里对_uid的脚本操作已经过期
                    "lang": "painless", 
                    "source": "doc['_id']" 
                }
            }
        }
    }
    

    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.

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

    GET website/_search
    {
        "query": {
            "terms": {"_id" : ["1", "2"]}
        },
        "aggs": {
            "id_aggs": {
                "terms": {
                    "field": "_id", "size": 10
                }
            }
        }, 
        "script_fields": {
            "id_script": {
                "script": {
                    "lang": "painless", 
                    "source": "doc['_id']"
                }
            }
        }
    }
    

    2 文档来源元字段

    2.1 _source - 文档原始JSON内容

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

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

    2.1.1 关闭_source功能

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

    PUT website
    {
        "mappings": {
            "blog": {
                "_source": {"enabled": false}
            }
        }
    }
    
    // 或者:
    PUT website/_mapping/blog
    {
        "_source": {"enabled": false}	
    }
    

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

    {
      "error": {
        "root_cause": [
          {
            "type": "resource_already_exists_exception",
            "reason": "index [website/zIUdhInBQsOUi_4Tt2SSkQ] already exists",
            "index_uuid": "zIUdhInBQsOUi_4Tt2SSkQ",
            "index": "website"
          }
        ],
        "type": "resource_already_exists_exception",
        "reason": "index [website/zIUdhInBQsOUi_4Tt2SSkQ] already exists",
        "index_uuid": "zIUdhInBQsOUi_4Tt2SSkQ",
        "index": "website"
      },
      "status": 400
    }
    

    2.1.2 查询时指定返回字段

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

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

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

    PUT logs
    {
        "mappings": {
            "event": {
                "_source": {
                    "includes": ["*.count", "meta.*"],         // 包含的字段
                    "excludes": ["meta.desc", "meta.other.*"]  // 不包含的字段
                }
            }
        }
    }
    

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

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

    GET website/blog/1?_source=false
    

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

    GET website/blog/1?_source_includes=title,content
    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的使用方法如下:

    PUT logs
    {
        "mappings": {
            "event": {
                "properties": {
                    "event_id": {
                        "type": "text",
                        "copy_to": {"enabled": true}	
                    },
                	  "event_desc": {
                        "type": "text",
                        "copy_to": {"enabled": true},
                        "analyzer": "english"
                    },
                    "time": {
                        "type": "date",
                        "copy_to": {"enabled": true},
                        "format": "strict_date_optional_time||epoch_millis"
                    }
                }
            }
        }
    }
    
    

    (2) ES 6.0以前的方法:

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

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

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

    PUT website/_mapping/blog
    {
        "_all": {"enabled": false}
    }
    

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

    PUT website/_mapping/blog
    {
        "properties": {
            "test_field": {
                "type": "text",
                "include_in_all": false
            }
        }
    }
    

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

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

    使用示例:

    GET website/_search
    {
        "query": {
            "terms": {"_field_names": ["content"]}
        }
    }
    

    4 路由元字段

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

    (1) 创建映射:

    PUT store
    {
        "mappings": {
            "book": {},
            "it_book": {
                "_parent": {"type": "book"}		// 指定其父类
            }
        }
    }
    

    (2) 插入父文档:

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

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

    PUT store/it_book/2?parent=1
    { "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的编号.

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

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

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

    GET website/_search
    {
        "query": {
            "terms": {"_routing": [ "user_5220" ] }
        }
    }
    

    5 其他元字段

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

    使用示例:

    PUT website
    {
        "mappings": {
            "user": {
                "_meta": {
                    "class": "com.healchow.website.pojo.User",
                    "version": {"min": "1.0", "max": "1.3"}
                }
            }
        }
    }
    

    参考资料

    Elasticsearch官方文档 - Meta-Fields

    版权声明

    作者: 马瘦风

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

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

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

  • 相关阅读:
    未格式化的输入/输出操作
    格式化输入与输出
    随机数
    正则表达式
    bitset
    tuple
    servlet笔记
    springside
    maven
    Lua简易入门教程
  • 原文地址:https://www.cnblogs.com/shoufeng/p/10679725.html
Copyright © 2011-2022 走看看