Elasticsearch中有几个关键属性容易混淆,不少人搞不清楚_source字段里存储的是什么?store属性的true或false和_source字段有什么关系?store属性设置为true和_all有什么关系?index属性又起到什么做用?何时设置store属性为true?何时应该开启_all字段?本文经过图解的方式,深刻理解Elasticsearch中的_source、_all、store和index属性。前端
如图1所示, 第二象限是一份原始文档,有title和content2个字段,字段取值分别为”我是中国人”和” 热爱”,这一点没什么可解释的。咱们把原始文档写入Elasticsearch,默认状况下,Elasticsearch里面有2分内容,一份是原始文档,也就是_source字段里的内容,咱们在Elasticsearch中搜索文档,查看的文档内容就是_source中的内容,如图2,相信你们必定很是熟悉这个界面。 mysql
另外一份是倒排索引,倒排索引中的数据结构是倒排记录表,记录了词项和文档之间的对应关系,好比关键词”中国人”包含在文档ID为1的文档中,倒排记录表中存储的就是这种对应关系,固然也包括词频等更多信息。Elasticsearch底层用的是Lucene的API,Elasticsearch之因此能完成全文搜索的功能就是由于存储的有倒排索引。若是把倒排索引拿掉,Elasticsearch是否是和mongoDB很像?
那么文档索引到Elasticsearch的时候,默认状况下是对全部字段建立倒排索引的(动态mapping解析出来为数字类型、布尔类型的字段除外),某个字段是否生成倒排索引是由字段的index属性控制的,在Elasticsearch 5以前,index属性的取值有三个:sql
analyzed:字段被索引,会作分词,可搜索。反过来,若是须要根据某个字段进搜索,index属性就应该设置为analyzed。
not_analyzed:字段值不分词,会被原样写入索引。反过来,若是某些字段须要彻底匹配,好比人名、地名,index属性设置为not_analyzed为佳。
no:字段不写入索引,固然也就不能搜索。反过来,有些业务要求某些字段不能被搜索,那么index属性设置为no便可。数据结构
再说_all字段,顾名思义,_all字段里面包含了一个文档里面的全部信息,是一个超级字段。以图中的文档为例,若是开启_all字段,那么title+content会组成一个超级字段,这个字段包含了其余字段的全部内容,固然也能够设置只存储某几个字段到_all属性里面或者排除某些字段。回到图一的第一象限,用户输入关键词" 中国人",分词之后,Elasticsearch从倒排记录表中查找哪些文档包含词项"中国人 ",注意变化,分词以前" 中国人"是用户查询(query),分词以后在倒排索引中" 中国人"是词项(term)。Elasticsearch根据文档ID(一般是文档ID的集合)返回文档内容给用户,如图一第四象限所示。一般状况下,对于用户查询的关键字要作高亮处理,如图3所示:app
关键字高亮实质上是根据倒排记录中的词项偏移位置,找到关键词,加上前端的高亮代码。这里就要说到store属性,store属性用于指定是否将原始字段写入索引,默认取值为no。若是在Lucene中,高亮功能和store属性是否存储息息相关,由于须要根据偏移位置到原始文档中找到关键字才能加上高亮的片断。在Elasticsearch,由于_source中已经存储了一份原始文档,能够根据_source中的原始文档实现高亮,在索引中再存储原始文档就多余了,因此Elasticsearch默认是把store属性设置为no。注意:若是想要对某个字段实现高亮功能,_source和store至少保留一个。下面会给出测试代码。至此,文章开头提出的几个问题都给出了答案。下面给出这几个字段经常使用配置的代码。测试
_source字段默认是存储的, 什么状况下不用保留_source字段?若是某个字段内容很是多,业务里面只须要能对该字段进行搜索,最后返回文档id,查看文档内容会再次到mysql或者hbase中取数据,把大字段的内容存在Elasticsearch中只会增大索引,这一点文档数量越大结果越明显,若是一条文档节省几KB,放大到亿万级的量结果也是很是可观的。 若是想要关闭_source字段,在mapping中的设置以下:spa
{ "yourtype":{ "_source":{ "enabled":false }, "properties": { ... } } }
若是只想存储某几个字段的原始值到Elasticsearch,能够经过incudes参数来设置,在mapping中的设置以下: .net
{ "yourtype":{ "_source":{ "includes":["field1","field2"] }, "properties": { ... } } }
一样,能够经过excludes参数排除某些字段:code
{ "yourtype":{ "_source":{ "excludes":["field1","field2"] }, "properties": { ... } } }
测试,首先建立一个索引,设置mapping,禁用_source:blog
PUT test/test/_mapping
{
"test": {
"_source": {
"enabled": false
}
}
}
POST test/test/1 { "title":"我是中国人", "content":"热爱" }
搜索关键词”中国人”:
GET test/_search { "query": { "match": { "title": "中国人" } } } { "took": 9, "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 } ] } }
从返回结果中能够看到,搜到了一条文档,可是禁用_source之后查询结果中不会再返回文档原始内容。(注,测试基于ELasticsearch 2.3.3,配置文件中已默认指定ik分词。
_all字段默认是关闭的,若是要开启_all字段,索引增大是不言而喻的。_all字段开启适用于不指定搜索某一个字段,根据关键词,搜索整个文档内容。
开启_all字段的方法和_source相似,mapping中的配置以下:
"yourtype": { "_all": { "enabled": true }, "properties": { ... } } }
也能够经过在字段中指定某个字段是否包含在_all中:
{ "yourtype": { "properties": { "field1": { "type": "string", "include_in_all": false }, "field2": { "type": "string", "include_in_all": true } } } }
若是要把字段原始值保存,要设置store属性为true,这样索引会更大,须要根据需求使用。设置mapping,这里设置全部字段都保存在_all中而且存储原始值:
PUT test/test/_mapping
{
"test": {
"_all": {
"enabled": true,
"store": true
}
}
}
POST test/test/1 { "title":"我是中国人", "content":"热爱" }
对_all字段进行搜索并高亮:
POST test/_search { "fields": ["_all"], "query": { "match": { "_all": "中国人" } }, "highlight": { "fields": { "_all": {} } } } { "took": 3, "timed_out": false, "_shards": { "total": 5, "successful": 5, "failed": 0 }, "hits": { "total": 1, "max_score": 0.15342641, "hits": [ { "_index": "test", "_type": "test", "_id": "1", "_score": 0.15342641, "_all": "我是中国人 热爱 ", "highlight": { "_all": [ "我是<em>中国人</em> 热爱 " ] } } ] } }
Elasticsearch中的query_string和simple_query_string默认就是查询_all字段,示例以下:
GET test/_search { "query": { "query_string": { "query": "公公公" } } }
index和store属性是在字段内进行设置的,下面给出一个例子,设置test索引不保存_source,title字段索引但不分析,字段原始值写入索引,content字段为默认属性,代码以下:
DELETE test PUT test PUT test/test/_mapping { "test": { "_source": { "enabled": false }, "properties": { "title": { "type": "string", "index": "not_analyzed", "store": "true" }, "content": { "type": "string" } } } }