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>!"
                    ]
                }
            }
        ]
    }
}
相關文章
相關標籤/搜索