您的当前位置:首页正文

ES系列十一、ES的index、store、_source、copy_to和all的区别

来源:爱站旅游
导读ES系列十一、ES的index、store、_source、copy_to和all的区别
ES系列⼗⼀、ES的index、store、_source、copy_to和all的区

1.基本概念

1.1._source

存储的原始数据。_source中的内容就是搜索api返回的内容,如:

{

\"query\":{ \"term\":{

\"title\":\"test\" } }}

结果:

{

\"took\": 2,

\"timed_out\": false, \"_shards\": { \"total\": 5,

\"successful\": 5, \"skipped\": 0, \"failed\": 0 },

\"hits\": {

\"total\": 1,

\"max_score\": 0.2876821, \"hits\": [ {

\"_index\": \"book3\", \"_type\": \"english\",

\"_id\": \"3nuFZ2UBYLvVFwGWZHcJ\", \"_score\": 0.2876821, \"_source\": {

\"title\": \"test!\" } } ] }}

默认情况下,Elasticsearch⾥⾯有2份内容,⼀份是原始⽂档,也就是_source字段⾥的内容,我们在Elasticsearch中搜索⽂档,查看的⽂档内容就是_source中的内容。另⼀份是倒排索引,倒排索引中的数据结构是倒排记录表,记录了词项和⽂档之间的对应关系。

1.2.index:索引

index使⽤倒排索引存储的是,分析器分析完的词和⽂档的对应关系。如图:

在搜索排序的时候,查询倒排索引要⽐快。

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

1. analyzed:字段被索引,会做分词,可搜索。反过来,如果需要根据某个字段进搜索,index属性就应该设置为analyzed。

2. not_analyzed:字段值不分词,会被原样写⼊索引。反过来,如果某些字段需要完全匹配,⽐如⼈名、地名,index属性设置为not_analyzed为佳。

3. no:字段不写⼊索引,当然也就不能搜索。反过来,有些业务要求某些字段不能被搜索,那么index属性设置为no即可。ES6.3 index属性⽀持false和true,false不能搜索相当于no,true可以索引。默认使⽤standar分词

1.3.store

默认为no,被store标记的fields被存储在和index不同的fragment中,以便于快速检索。虽然store占⽤磁盘空间,但是减少了计算。store的值可以取yes/no或者true/false,默认值是no或者false。

如果在{\"store\":yes}的情况下,ES会对该字段单独存储倒排索引,每次根据ID检索的时候,会多⾛⼀次IO来从倒排索引取数据。⽽如果_source enabled 情况下,ES可以直接根据Client类来解析_source JSON,只需⼀次IO就将所有字段都检索出来了。

如果需要⾼亮处理,这⾥就要说到store属性,store属性⽤于指定是否将原始字段写⼊索引,默认取值为no。如果在Lucene中,⾼亮功能和store属性是否存储息息相关,因为需要根据偏移位置到原始⽂档中找到关键字才能加上⾼亮的⽚段。在Elasticsearch,因为_source中已经存储了⼀份原始⽂档,可以根据_source中的原始⽂档实现⾼亮,在索引中再存储原始⽂档就多余了,所以Elasticsearch默认是把store属性设置为no。

注意:如果想要对某个字段实现⾼亮功能,_source和store⾄少保留⼀个。

1.4._all

_all: 在6.0+ 中 , 该字段 默认被禁⽤,建议使⽤copy_to。再说_all字段,顾名思义,_all字段⾥⾯包含了⼀个⽂档⾥⾯的所有信息,是⼀个超级字段。以图中的⽂档为例,如果开启_all字段,那么title+content会组成⼀个超级字段,这个字段包含了其他字段的所有内容,空格隔开。当然也可以设置只存储某⼏个字段到_all属性⾥⾯或者排除某些字段。适合⼀次搜索整个⽂档。

2.配置

2.1._source配置

_source字段默认是存储的, 什么情况下不⽤保留_source字段?如果某个字段内容⾮常多,业务⾥⾯只需要能对该字段进⾏搜索,最后返回⽂档id,查看⽂档内容会再次到mysql或者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\": { ... } }}

测试,⾸先创建⼀个索引:

PUT book2

设置mapping,禁⽤_source:

POST book2/english/_mapping{

\"book2\": { \"_source\": {

\"enabled\": false } }}

插⼊数据:

POST /book2/english/{

\"title\":\"test!\",

\"content\":\"test good Hellow\"}

搜索\"test\"

POST book2/_search{

\"query\":{ \"term\":{

\"title\":\"test\" } }}

结果,只返回了id,没有_suorce,任然可以搜索到。

{

\"took\": 5,

\"timed_out\": false, \"_shards\": { \"total\": 5,

\"successful\": 5, \"skipped\": 0, \"failed\": 0 },

\"hits\": {

\"total\": 1,

\"max_score\": 0.2876821, \"hits\": [ {

\"_index\": \"book2\", \"_type\": \"english\",

\"_id\": \"zns1Z2UBYLvVFwGW4Hea\", \"_score\": 0.2876821 } ] }}

当_source=false,store和index必须有⼀个为true,原始数据不保存,倒排索引必须要存储,否则去哪⾥查询呢,验证下:

POST book3/english/_mapping{

\"english\":{ \"_source\": {

\"enabled\": false },

\"properties\": { \"content\":{

\"type\":\"text\", \"store\":\"false\", \"index\":\"no\" },

\"title\":{

\"type\":\"text\", \"store\":\"false\", \"index\":\"no\" } } }

}

报错:

{

\"error\": {

\"root_cause\": [ {

\"type\": \"illegal_argument_exception\",

\"reason\": \"Could not convert [content.index] to boolean\" } ],

\"type\": \"illegal_argument_exception\",

\"reason\": \"Could not convert [content.index] to boolean\", \"caused_by\": {

\"type\": \"illegal_argument_exception\",

\"reason\": \"Failed to parse value [no] as only [true] or [false] are allowed.\" } },

\"status\": 400}

2.2._all配置(copy_to)

_all: 在6.0+ 中 , 该字段 默认被禁⽤,同时在创建index的时候不能 enable;_all 字段能捕获所有字段,它将所有其他字段的值连接成⼀个⼤字符串,使⽤空格作为分隔符,然后 进⾏分析和索引,但不存储。这意味着它可以被搜索,但不能被检索。 建议使⽤ copy_to实现 ⽤户⾃定义的_all 功能

{

\"yourtype\": { \"_all\": {

\"enabled\": true },

\"properties\": { ... } }}

也可以通过在字段中指定某个字段是否包含在_all中:

{

\"yourtype\": { \"properties\": { \"field1\": {

\"type\": \"string\",

\"include_in_all\": false },

\"field2\": {

\"type\": \"string\",

\"include_in_all\": true } } }}

如果要把字段原始值保存,要设置store属性为true,这样索引会更⼤,需要根据需求使⽤。下⾯给出测试代码。 创建test索引:

DELETE book2PUT book2

copy_to语法:

POST book2/english/_mapping{

\"english\":{

\"properties\": { \"content\":{

\"type\":\"text\",

\"copy_to\":\"all_text\" },

\"title\":{

\"type\":\"text\",

\"copy_to\":\"all_text\" },

\"all_text\":{

\"type\":\"text\" } }

}}

插⼊数据:

POST /book2/english/{

\"title\":\"test!\",

\"content\":\"test good Hellow\"}

查询:

POST book2/_search{ \"query\":{ \"term\":{

\"all_text\":\"test\" } }}

结果:

{

\"took\": 13,

\"timed_out\": false, \"_shards\": { \"total\": 5,

\"successful\": 5, \"skipped\": 0, \"failed\": 0 },

\"hits\": {

\"total\": 2,

\"max_score\": 0.39556286, \"hits\": [ {

\"_index\": \"book2\", \"_type\": \"english\",

\"_id\": \"0HtjZ2UBYLvVFwGWl3f7\", \"_score\": 0.39556286, \"_source\": {

\"title\": \"test!god\",

\"content\": \"test good Hellow\" } }, {

\"_index\": \"book2\", \"_type\": \"english\",

\"_id\": \"z3tjZ2UBYLvVFwGWWXd3\", \"_score\": 0.39556286, \"_source\": {

\"title\": \"test!\",

\"content\": \"test good Hellow\" } } ] }}

2.3.index和score配置

\"index\":false设置不可搜索

POST book3/english/_mapping{

\"english\":{ \"_source\": {

\"enabled\": false },

\"properties\": { \"content\":{ \"type\":\"text\", \"store\":true, \"index\":false },

\"title\":{

\"type\":\"text\", \"store\":true, \"index\":false } } }

}

查询:

POST book3/_search{

\"query\":{ \"term\":{

\"content\":\"test\" } }}

结果:{

\"error\": {

\"root_cause\": [ {

\"type\": \"query_shard_exception\",

\"reason\": \"failed to create query: {\\n \\\"term\\\" : {\\n \\\"content\\\" : {\\n \\\"value\\\" : \\\"test\\\, \"index_uuid\": \"FvNPHNb7Sa6H757_lKRhpg\", \"index\": \"book3\" } ],

\"type\": \"search_phase_execution_exception\", \"reason\": \"all shards failed\", \"phase\": \"query\", \"grouped\": true, \"failed_shards\": [ {

\"shard\": 0,

\"index\": \"book3\",

\"node\": \"R8t6R20XQritJB_5QVQsvg\", \"reason\": {

\"type\": \"query_shard_exception\",

\"reason\": \"failed to create query: {\\n \\\"term\\\" : {\\n \\\"content\\\" : {\\n \\\"value\\\" : \\\"test\\\, \"index_uuid\": \"FvNPHNb7Sa6H757_lKRhpg\", \"index\": \"book3\", \"caused_by\": {

\"type\": \"illegal_argument_exception\",

\"reason\": \"Cannot search on field [content] since it is not indexed.\" } } } ] },

\"status\": 400}

正确配置:

POST book3/english/_mapping{

\"english\":{ \"_source\": {

\"enabled\": false },

\"properties\": { \"content\":{ \"type\":\"text\", \"store\":true, \"index\":\"true\" },

\"title\":{

\"type\":\"text\", \"store\":true, \"index\":\"true\" } } }}

⾼亮:

{

\"query\":{ \"term\":{

\"title\":\"test\" } },

\"highlight\":{

\"fields\":{ \"title\":{} } }}

结果:

{

\"took\": 4,

\"timed_out\": false, \"_shards\": { \"total\": 5,

\"successful\": 5, \"skipped\": 0, \"failed\": 0 },

\"hits\": {

\"total\": 1,

\"max_score\": 0.2876821, \"hits\": [ {

\"_index\": \"book3\", \"_type\": \"english\",

\"_id\": \"2nt_Z2UBYLvVFwGWfXcn\", \"_score\": 0.2876821, \"highlight\": { \"title\": [

\"test!\" ] } } ] }}

因篇幅问题不能全部显示,请点此查看更多更全内容

Top