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

1.基本概念

1.1._source

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

{
 "query":{
  "term":{
   "title":"test"
  }
 }
}

结果:mysql

{
    "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中的内容。另外一份是倒排索引,倒排索引中的数据结构是倒排记录表,记录了词项和文档之间的对应关系。sql

1.2.index:索引

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

在搜索排序的时候,查询倒排索引要比快。数据结构

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

  1. analyzed:字段被索引,会作分词,可搜索。反过来,若是须要根据某个字段进搜索,index属性就应该设置为analyzed。
  2. not_analyzed:字段值不分词,会被原样写入索引。反过来,若是某些字段须要彻底匹配,好比人名、地名,index属性设置为not_analyzed为佳。
  3. no:字段不写入索引,固然也就不能搜索。反过来,有些业务要求某些字段不能被搜索,那么index属性设置为no便可。

ES6.3 index属性支持false和true,false不能搜索至关于no,true能够索引。默认使用standar分词svg

1.3.store

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

若是在{"store":yes}的状况下,ES会对该字段单独存储倒排索引,每次根据ID检索的时候,会多走一次IO来从倒排索引取数据。ui

而若是_source enabled 状况下,ES能够直接根据Client类来解析_source JSON,只需一次IO就将全部字段都检索出来了。spa

若是须要高亮处理,这里就要说到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  book2

PUT 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\",\n      \"boost\" : 1.0\n    }\n  }\n}",
                "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\",\n      \"boost\" : 1.0\n    }\n  }\n}",
                    "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": [
                        "<em>test</em>!"
                    ]
                }
            }
        ]
    }
}
相关文章
相关标签/搜索