文章目录
元字段是ES为每个文档配置的内置字段, 主要用于ES内部相关操作.
1 标识元字段
1.1 _index - 文档所属的索引
_index
标注document属于哪个index, 是一个虚拟字段, 不会被添加到Lucene索引中.
将类似的文档 (即具有相同field的文档) 存放到同一个index中, 是一种良好的数据建模思想 —— 可以将index路由到指定的shard上, 便于系统的优化:
承担大量查询的index所在的shard上, 不宜存储需要频繁聚合分析的index, 反之同理.
在term或者terms查询, 聚合、脚本以及排序时, 可以访问_index
字段的值.
在多个索引中执行查询时, 可以通过添加查询子句来关联特定的索引文档.
注意: 索引名称必须是小写的字母, 不能以下划线"_“开头, 不能包含逗号”,".
-
使用示例:
GET website,shop/_search { "query": { "terms": {"_index": ["website", "shop"]} }, "aggs": { "indices": { "terms": {"field": "_index", "size": 10} } }, "sort": { "_index": {"order": "asc"} }, "script_fields": { "index_name": { "script": { "lang": "painless", "source": "doc['_index']" } } } }
1.2 _uid - 包含_type和_id的混合字段
_uid
是_type
和_id
的组合, 形式为{type}#{id}
. 可用于查询、聚合、脚本和排序:
-
添加文档:
PUT website/blog/4 { "text": "blog with ID 4" } PUT website/blog/5?refresh=true { "text": "blog with ID 5" }
-
检索文档:
GET website/_search { "query": { "terms": {"_uid": ["blog#4", "blog#5"]} }, "aggs": { "uid aggs": { "terms": {"field": "_uid", "size": 10} } }, "sort": { "_uid": { "order": "desc"} }, "script_fields": { "uid script": { "script": { "lang": "painless", "source": "doc['_uid']" } } } }
1.3 _type - 文档的类型
标注document属于哪个类型, 也被称作映射类型.
一个index可能会被划分为多个type, 例如: 商品中有电子商品, 服装商品, 生鲜商品…
注意: type的名称可以是大写或小写字母, 但不能以下划线"_“开头, 不能包含逗号”,".
每一个索引文档都包含_type
和_id
字段, _type
字段的目的是通过类型名加快搜索速度.
_type字段可以在查询、聚合、排序以及脚本中访问到.
关于type的底层数据结构, 可参见☆type的底层.
1.4 _id - 文档的id
_id
代表document的唯一标识, 与_index
和_type
一起, 唯一标识和定位一个document.
此字段不会被索引, 可以从_uid
字段中自动生成.
注意: 可以手动指定document的id(put /index/type/id), 也可以不指定, ES会自动创建.
请参见文章: ☆手动和自动生成id的文章
可以在查询、脚本中访问, 但是在聚合或排序时, 要使用_uid
.
-
查询示例:
GET website/_search { "query": { "terms": {"_id" : ["1", "2"]} }, "aggs": { "UIDs aggs": { "terms": { "field": "_uid", "size": 10 } } }, "script_fields": { "UID script": { "script": { "lang": "painless", "source": "doc['_uid']" // 这里使用_uid } } } }
2 文档来源元字段
2.1 _source - 文档原始JSON内容
文档的原始JSON内容将索引到_source
字段中, 该字段本身不建立索引, 但是会被存储.
搜索文档时默认返回该字段及其内容, 但无法用于搜索.
2.1.1 关闭_source功能
_source
功能默认是开启的, 它会产生额外的存储开销, 可以关闭:
PUT website
{
"mappings": {
"blog": {
"_source": {"enabled": false}
}
}
}
注意: 必须在创建索引时关闭, 创建之后不允许修改.
_source功能被禁止, 将造成大量功能无法使用:
partial update 功能基于_source实现;
hilight 高亮显示功能基于_source实现;
reindex 重建索引功能基于_source实现, 不需要从其他外部存储中获取数据, 再index;
基于_source定制返回field;
调试query时更容易, 因为可以很直观地看到_source内容.
……
可以使用includes/excludex
参数来减少_source
字段的内容:
PUT logs
{
"mapping": {
"event": {
"_source": {
"include": ["*.count", "meta.*"],
"exclude": ["meta.desc", "meta.other.*"]
}
}
}
}
移除的字段不会被存储在_source中, 但仍然可以搜索到这些字段.
2.1.2 查询时指定返回字段
可以禁止返回原始内容:
GET website/blog/1?_source=false
如果只想获取_source
的部分内容, 可以使用_source_include
或_source_exclude
参数:
GET website/blog/1?_source_include=title,content
GET website/blog/1?_source_exclude=post_date,author_id
2.1.3 禁用_source
PUT website/_mapping/blog
{
"_source": {"enabled": false} // 要在初次创建时设置, 如果索引已经建立, 就不能再修改了
}
2.2 _size - _source字段占用的字节数
记录_source
字段占用的字节数, 由插件mapper-size提供.
3 索引元字段
3.1 _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 - 在映射类型间创建父子关系
4.1.1 使用示例
-
创建映射:
PUT store { "mappings": { "book": {}, "it_book": { "_parent": {"type": "book"} // 指定其父类 } } }
-
插入父文档:
PUT store/book/1 { "desc": "this is parent book"}
-
插入子文档, 并指出其父文档:
PUT store/it_book/2?parent=1 { "desc": "this is child it_book"}
4.1.2 父子文档的限制
① 父type和子type必须不同.
② _parent的type的值只能是不存在的类型 —— 一个type被创建后就不能称为父类型了.
说明:
父子文档必须索引在同一个分片上
–> parent的编号用于子文档的路由值, 确保子文档被索引到父文档所在的分片中.
–> 查询、更新、删除子文档时, 也需要提供相同的parent值.
4.2 _routing - 自定义的路由值
用于将文档路由到指定的分片上. 通过如下公式将文档路由到特定的分片:
shard_num = hash(_routing) % num_primary_shards
如果不指定_routing
的值, 默认使用文档的_id
字段. 如果存在父文档则使用其_parent
的编号.
可以通过为某些文档都指定相同的路由值, 来实现对这些文档的自定义路由功能:
PUT website/blog/1?routing=user_5220
{
"title": "xxx"
}
// 此文档使用'user_5220'作为其路由值, 在查询、更新、删除时同样需要提供此路由值
_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技术解析与实战》
版权声明
作者: ma_shoufeng(马瘦风)
出处: CSDN 马瘦风的博客
您的支持是对博主的极大鼓励, 感谢您的阅读.
本文版权归博主所有, 欢迎转载, 但未经博主同意必须保留此段声明, 且在文章页面明显位置给出原文链接, 否则博主保留追究相关人员法律责任的权利.