Elasticsearch中有大量关键概念容易混淆,对于初学者来说是噩梦:

  • _source字段里存储了什么?
  • index属性的作用是什么?
  • 何时应该开启_all字段?
  • store属性和_source字段有什么关系?
  • store属性和_all字段有什么关系?
  • 什么情况下不用保留_source字段?

本文通过问答及展开描述的方式,深入理解Elasticsearch中的_source_all字段和storeindex属性。

概念解释

Q:_source字段里存储了什么?
A:原始文档的内容。

图1 Elasticsearch中的_source、_all、store和index属性解析

如图1所示, 第二象限是一份原始文档,有titlecontent2个字段,字段取值分别为"我是中国人"和"热爱gongchangdang",这一点没什么可解释的。我们把原始文档写入Elasticsearch,默认情况下,Elasticsearch里面有2份内容,一份是原始文档,也就是_source字段里的内容,我们在Elasticsearch中搜索文档,查看的文档内容就是_source中的内容,如图2,相信大家一定非常熟悉这个界面。

图2 _source字段举例

另一份是倒排索引,倒排索引中的数据结构是倒排记录表,记录了词项和文档之间的对应关系,比如关键词"中国人"包含在文档ID为1的文档中,倒排记录表中存储的就是这种对应关系,当然也包括词频等更多信息。Elasticsearch底层用的是Lucene的API,Elasticsearch之所以能完成全文搜索的功能就是因为存储有倒排索引。如果把倒排索引拿掉,Elasticsearch是不是和mongoDB很像?

Q:index属性的作用是什么?
A:控制field是否生成倒排索引以及生成索引时是否做分词。

那么文档索引到Elasticsearch的时候,默认情况下是对所有字段创建倒排索引的(动态mapping解析出来为数字类型、布尔类型的字段除外),某个字段是否生成倒排索引是由字段的index属性控制的,在Elasticsearch 5之前,index属性的取值有三个:

  • analyzed:字段被索引,会做分词,可搜索。反过来,如果需要根据某个字段进行搜索,index属性就应该设置为analyzed
  • not_analyzed:字段值不分词,会被原样写入索引。反过来,如果某些字段需要完全匹配,比如人名、地名,index属性设置为not_analyzed为佳。
  • no:字段不写入索引,当然也就不能搜索。反过来,有些业务要求某些字段不能被搜索,那么index属性设置为no即可。

Q:何时应该开启_all字段?
A:_all字段开启适用于不指定搜索某一个字段,根据关键词,搜索整个文档内容。

再说_all字段,顾名思义,_all字段是把所有其它字段中的值,以空格为分隔符组成一个大字符串,然后被分析和索引,但是不存储,也就是说它能被查询,但不能被取回显示,是一个超级字段。以图中的文档为例,如果开启_all字段,那么title和content的值会组成一个超级字段,当然也可以设置只存储某几个字段到_all属性里面或者排除某些字段。_all字段在查询时占用更多的CPU和占用更多的磁盘空间,如果确实不需要它可以完全的关闭它或者基于字段定制。

_all能让你在不知道要查找的内容是属于哪个具体字段的情况下进行搜索,例如:

PUT my_index/user/1
{
"first_name": "John",
"last_name": "Smith",
"date_of_birth": "1970-10-24"
}
GET my_index/_search
{
"query": {
"match": {
"_all": "john smith 1970"
}
}
}

得到的结果是:

{
"took": 20,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 0.84748024,
"hits": [
{
"_index": "my_index",
"_type": "user",
"_id": "1",
"_score": 0.84748024,
"_source": {
"first_name": "John",
"last_name": "Smith",
"date_of_birth": "1970-10-24"
}
}
]
}
}

Q:store属性和_source字段有什么关系?
A:_source是字段,store是字段的属性之一,Elasticsearch默认会存储一份_source字段作为原始文档。store属性和_source字段配合进行设置可以决定字段的检索方式和是否高亮展示。

回到图一的第一象限,用户输入关键词"中国人",分词以后,Elasticsearch从倒排记录表中查找哪些文档包含词项"中国人 ",注意变化,分词之前" 中国人"是用户查询(query),分词之后在倒排索引中" 中国人"是词项(term)。Elasticsearch根据文档ID(通常是文档ID的集合)返回文档内容给用户,如图一第四象限所示。

通常情况下,对于用户查询的关键字要做高亮处理,如图3所示:

图3 搜索引擎中的关键字高亮

关键字高亮实质上是根据倒排记录中的词项偏移位置,找到关键词,加上前端的高亮代码。这里就要说到store属性,store属性用于指定是否将原始字段写入索引,默认取值为false。如果在Lucene中,高亮功能和store属性是否存储息息相关,因为需要根据偏移位置到原始文档中找到关键字才能加上高亮的片段。两者不同取值时对字段检索和高亮的影响如下表:

enabled store为true的字段从倒排索引里检索,浪费IO次数; 所有字段根据Client类解析存储的 _source JSON串进行检索,仅需一次IO;
disabled store为true的字段从倒排索引里检索,其他字段能检索不能高亮展示; 所有字段只能检索,不能高亮展示;
_source\store
true
false

在Elasticsearch,因为_source中已经存储了一份原始文档,可以根据_source中的原始文档实现高亮,在索引中再存储原始文档就多余了,所以Elasticsearch默认是把store属性设置为false

如果想要对某个字段实现高亮功能,_sourcestore至少保留一个。下面给出一个例子,设置test索引不保存_source,title字段索引但不分析,字段原始值写入索引,content字段为默认属性,代码如下:

  • 新建test index:
PUT test/test/_mapping
{
"test": {
"_source": {
"enabled": false
},
"properties": {
"title": {
"type": "string",
"index": "not_analyzed",
"store": "true"
},
"content": {
"type": "string"
}
}
}
}
  • 对title字段进行搜索并高亮:
GET test/_search
{
"query": {
"match": {
"title": "我是中国人"
}
},
"highlight": {
"fields": {
"title": {}
}
}
}
  • 返回结果:
{
"took": 6,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 0.30685282,
"hits": [
{
"_index": "test",
"_type": "test",
"_id": "1",
"_score": 0.30685282,
"highlight": {
"title": [
"<em>我是中国人</em>"
]
}
}
]
}
}

从返回结果中可以看到,虽然没有保存title字段到_source, 但是依然可以实现搜索高亮。

{"store": true}既然这么费力不讨好,但是仍然有两个应用场景:

  • 文档很长,检索所有文档或者存储所有文档、获取所有field的代价比较大;
  • 仅仅针对某几个字段进行re-index的时候;

Q:store属性和_all字段有什么关系?
A:_all字段拥有store属性,是从属关系。store属性决定了_all字段是否可以被高亮展示。

首先store_all字段的一个属性,_all字段默认不属于_source,并且store属性默认为false,所以不能被高亮展示。如果希望被高亮展示,则有两种方式:

  • 设置_all字段的store为true,代价是大量的冗余存储;
  • 对原始字段进行高亮;

Q:什么情况下不用保留_source字段?
A:需要存储海量文档,Elasticsearch在架构中只做索引,存储选型为类似HBase的NoSQL,不存储_source可以极大减少存储开销(Elasticsearch往往用的是SSD)。

_source字段默认是存储的, 什么情况下不用保留_source字段?如果某个字段内容非常多,业务只需要能对该字段进行搜索,最后返回文档id,查看文档内容会再次到HBase中取数据,把大字段的内容存在Elasticsearch中只会增大索引,这一点文档数量越大结果越明显,如果一条文档节省几KB,放大到亿万级的量结果也是非常可观的。 如果想要关闭_source字段,在mapping中的设置如下:

{
"yourtype":{
"_source":{
"enabled":false
},
"properties": {
...
}
}
}

如果只想存储某几个字段的原始值到Elasticsearch,可以通过incudes参数来设置,在mapping中的设置如下:

{
"yourtype":{
"_source":{
"includes":["field1","field2"]
},
"properties": {
...
}
}
}

同样,可以通过excludes参数排除某些字段:

{
"yourtype":{
"_source":{
"excludes":["field1","field2"]
},
"properties": {
...
}
}
}

小结

至此,文章开头提出的几个问题都给出了答案。特别参考了这篇文章:图解Elasticsearch中的_source、_all、store和index属性


作者:大数据之心
链接:http://www.jianshu.com/p/0908b9ee65fc
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

浅析ES的_source、_all、store、index的更多相关文章

  1. ES索引瘦身 压缩——_source _all 均disable filed store为no,引入第三方DB存储原始数据,去掉pos倒排和doc_values,强制定期merge segments,将所有fileds合并为一个field big string

    原始数据:835MB ES 设置了_source _all disabled 且设置了仅仅存docs倒排Wed Feb 22 11:58:27 CST 2017Before size:1 /home/ ...

  2. elasticsearch中mapping的_source和store的笔记

    0.故事引入 无意中看到了ES的mapping中有store字段,作为一个ES菜鸡,有必要对这个字段进行下笔记. 1._source _source字段我在们进行检索时相当重要, ES默认检索只会返回 ...

  3. elasticsearch中mapping的_source和store的笔记(转)

    原文地址: https://www.cnblogs.com/zklidd/p/6149120.html 0.故事引入 无意中看到了ES的mapping中有store字段,作为一个ES菜鸡,有必要对这个 ...

  4. 踩坑记录-nuxt引入vuex报错store/index.js should export a method that returns a Vuex instance.

    错误 store/index.js代码如下: import Vue from 'vue'; import Vuex from 'vuex'; import city from './moudle/ci ...

  5. ES禁用_source不会影响聚合

    From Elasticsearch's website: The _source field contains the original JSON document body that was pa ...

  6. es关闭不使用的index、真正删除文档

    因为只要索引处于open状态,就会占用内存+磁盘: 如果将索引close,只会占用磁盘 Curl -XPOST ‘hadoop01:9200/index/_close’ ------ 在es中删除文档 ...

  7. lucene LZ4 会将doc存储在一个chunk里进行Lz4压缩 ES的_source便如此

    默认情况下,Elasticsearch 用 JSON 字符串来表示文档主体保存在 _source 字段中.像其他保存的字段一样,_source 字段也会在写入硬盘前压缩.The _source is ...

  8. ES建立索引步骤, 1,index 2.mapping 3,别名

    1.建立索引PUT /index_trans_detail 2.建立mappingPOST /index_trans_detail/type_trans_detail/_mapping{ " ...

  9. Column store index 列数据如何匹配成行数据?

    SQL Server 2012引入了列存储索引,对每列的数据进行分组和存储,然后联接所有列以完成整个索引.这不同于传统索引,传统索引对每行的数据进行分组和存储,然后联接所有行以完成整个索引. 在访问基 ...

随机推荐

  1. curl命令测试服务器是否支持断点续传

     通过curl命令测试服务器是否支持断点续传 curl -i --range 0-9 http://www.baidu.com/img/bdlogo.gif HTTP/1.1 206 Partial ...

  2. mysql服务命令行操作

    启动 net start mysql 关闭 net stop mysql 登陆 mysql -hlocalhost -uusername -ppassword 退出 exit 显示数据库 show d ...

  3. JavaWeb学习篇之----Tomcat中配置数字证书以及网络传输数据中的密码学知识

    今天是学习JavaWeb的第二天,我们来了解什么呢?就了解一下Tomcat中配置数字证书的相关内容,但是在说这部分内容的时候,我们貌似得先说一下数字证书的相关概念,那说到数字证书的时候我们还得了解一些 ...

  4. bzoj1001题解

    [解题思路] 显然,这题的答案是这个网格图的最小割.根据最大流-最小割定理,我们可以用网络流算法来求其最小割,时间复杂度最小为O(V2√E). 特殊的,这个网格图是一个平面图,于是可以根据平面图最小割 ...

  5. curl命令,curl实现post,curl监控网页shell脚本,curl多进程实现并控制进程数,

    cURL > Docs > Tutorial:  http://curl.haxx.se/docs/httpscripting.html 下载单个文件,默认将输出打印到标准输出中(STDO ...

  6. Java-javaFx库运用-时钟显示

    JavaFx是开发Java GUI程序的新框架.JavaFX应用可以无缝地在桌面或web浏览器中运行.具有内建的2D.3D动画支持,以及视频和音频的回放功能,可以作为一个应用独立运行或者在浏览器中运行 ...

  7. Java-Class-I:java.util.List

    ylbtech-Java-Class-I:java.util.List 1.返回顶部 1.1.import java.util.ArrayList;import java.util.List; 1.2 ...

  8. CSS3:教程

    ylbtech-CSS3:教程 1.返回顶部 1. CSS3 教程 CSS 用于控制网页的样式和布局. CSS3 是最新的 CSS 标准. 本教程向您讲解 CSS3 中的新特性. 开始学习 CSS3! ...

  9. Spring源码由浅入深系列六 CreateBean过程

  10. HDU-1226-超级密码-队列+广搜+大数取模

    Ignatius花了一个星期的时间终于找到了传说中的宝藏,宝藏被放在一个房间里,房间的门用密码锁起来了,在门旁边的墙上有一些关于密码的提示信息: 密码是一个C进制的数,并且只能由给定的M个数字构成,同 ...