1. 程式人生 > >小白學ES 11 - 什麼是Elasticsearch的對映(mapping) + 如何配置對映

小白學ES 11 - 什麼是Elasticsearch的對映(mapping) + 如何配置對映

文章目錄

1 對映的相關概念

1.1 什麼是對映

① 對映(mapping): 定義index的元資料, 指定要索引並存儲的文件的欄位型別.

—— 即對映決定了Elasticsearch在建立倒排索引、進行檢索時對文件採取的相關策略, 如數字型別、日期型別、文字型別等等.

—— 檢索時的分析策略, 要與建立索引時的分析策略相同, 否則將導致資料不準確.

② ES對不同的型別有不同的儲存和檢索策略.

—— 如對full text型的資料型別(如text), 在索引時, 會經過各類處理, 比如分詞、normalization(時態轉換、同義詞轉換、大小寫轉換)等, 才會建立到索引中.

—— 如對exact value(如date), 在索引的分詞階段, 會將整個value作為一個關鍵詞建立到倒排索引中.

1.2 對映的組成

每個index都有一至多個type, 每個type對應一個mapping. 每個mapping都由下述部分組成:

① 元欄位: _index_type_id_source.

② field/properties(欄位或屬性): 同一index的不同type中, 同名的field的對映配置必須相同

—— 因為index是根據_type 元欄位來區分type的, 即儲存的每個文件中都有_type等元欄位, 若相同名稱的field的對映(_type

欄位的值)不同, Elasticsearch在解析時就會出現衝突.

—— 這些引數可以例外: copy_to、dynamic、enabled、ignore_above、include_in_all.

關於type的處理方法, 詳見部落格☆type的底層結構

1.3 元欄位

每個文件都有與之關聯的元資料 —— ES內部為所有的文件配備的field, 都是以下劃線"_"開頭的內建欄位.

具體的內容將在博文 Elasticsearch的元欄位 中詳細講解.

1.4 欄位的型別

Elasticsearch中每個field都對應一至多個數據型別.

這部分的內容在博文 Elasticsearch欄位的型別 中詳細講解.

2 如何配置mapping

2.1 建立mapping

2.1.1 必讀事項

  • 建立mapping時, 可以指定每個field是否需要:

    索 引: “index”: true —— 預設配置

    不索引: “index”: false

  • 說明:

    這裡使用的是Elasticsearch 5.6.10版本, 是否索引的API已經做了修改, 若使用"analyzed" | “not_analyzed” | “yes” | "no"等, 將丟擲如下警告:

    #! Deprecation: Expected a boolean [true/false] for property [index] but got [not_analyzed]
    #! Deprecation: Expected a boolean [true/false] for property [index] but got [no]
    
  • mapping root object:

    每個type對應的mapping的JSON串, 包括properties, metadata(_id, _source, _type) , settings(analyzer) , 其他settings(如include_in_all)

2.1.2 建立示例

需求: 建立名為website的索引, 包含user和blog兩個type. user型別中禁用元欄位_all.

PUT website
{
    "mappings": {
        "user": {								// 此即為一個root object
            "_all": { "enabled": false },		// 禁用_all欄位
            "properties": {
            	"name": { "type": "text" },
                "age": { "type": "integer" },
                "sex": { "type": "keyword" }
            }
        }, 
        "blog": {
            "properties": {
                "author_id": { "type": "text" },
                "title": {
                    "type": "text",
                    "analyzer": "english"
                },
                "content": { "type": "text" },
            	"publisher_id": {
                    "type": "text",
                    "index": false					// 不分詞
                }, 
                "post_date": { 
                    "type": "date", 
                    "format": "strict_date_optional_time||epoch_millis"
                }
            }
        }
    }
}

2.2 更新mapping

2.2.1 必讀事項

  • 對映一旦建立完成, 就不允許修改:

    —— Elasticsearch將文件索引並存儲的過程中, 就是按照對映中的配置進行的. 如果後期修改了對映, 檢索時對索引的處理將存在不一致的情況.

  • 只能建立index時手動建立mapping, 或者新增field mapping, 但是不能update field mapping

2.2.2 更新mapping出現異常

  • 修改已經建立好的mapping

    PUT website
    {
        "mappings": {
            "blog": {
                "properties": {
                    "author_id": { "type": "text" }
                }
            }
        }
    }
    
  • 丟擲如下錯誤 —— 索引已經存在的異常:

    {
      "error": {
        "root_cause": [
          {
            "type": "index_already_exists_exception",
            "reason": "index [website/co1dgJ-uTYGBEEOOL8GsQQ] already exists",
            "index_uuid": "co1dgJ-uTYGBEEOOL8GsQQ",
            "index": "website"
          }
        ],
        "type": "index_already_exists_exception",
        "reason": "index [website/co1dgJ-uTYGBEEOOL8GsQQ] already exists",
        "index_uuid": "co1dgJ-uTYGBEEOOL8GsQQ",
        "index": "website"
      },
      "status": 400
    }
    

2.2.3 向mapping中新增新type

  • 向已有mapping中新增欄位及其對映資訊:

    PUT website/_mapping/blog		// 修改blog型別的_mapping, 注意API的順序
    {
        "properties": {
            "new_field": {
                "type": "text",
                "index": false
            }
        }
    }
    

2.3 測試mapping

2.3.1 檢視mapping

GET website/_mapping

// 響應資訊如下: 
{
  "website": {
    "mappings": {
      "user": {
        "_all": {
          "enabled": false			// 禁用_all元欄位
        },
        "properties": {
          "age": {
            "type": "integer"
          },
          "name": {
            "type": "text"
          },
          "sex": {
            "type": "keyword"
          }
        }
      },
      "blog": {
        "properties": {
          "author_id": {
            "type": "long"
          },
          "content": {
            "type": "text"
          },
          "new_field": {
            "type": "text",
            "index": false			// 不索引
          },
          "post_date": {
            "type": "date"
          },
          "publisher_id": {
            "type": "text",
            "index": false			// 不索引
          },
          "title": {
            "type": "text",
            "analyzer": "english"
          }
        }
      }
    }
  }
}

2.3.2 對不索引的field進行分詞

"new_field"作了不索引的處理, 對其強行分詞:

GET website/_analyze
{
  "field": "new_field",
  "text": "shou feng"
}

應該丟擲如下錯誤:

{
  "error": {
    "root_cause": [
      {
        "type": "remote_transport_exception",
        "reason": "[jVSUBme][10.0.20.50:9300][indices:admin/analyze[s]]"
      }
    ],
    "type": "illegal_argument_exception",
    "reason": "Can't process field [new_field], Analysis requests are only supported on tokenized fields"
  },
  "status": 400
}

可是卻正常分詞了 —— 具體原因尚不可知:

{
  "tokens": [
    {
      "token": "shou",
      "start_offset": 0,
      "end_offset": 4,
      "type": "<ALPHANUM>",
      "position": 0
    },
    {
      "token": "feng",
      "start_offset": 5,
      "end_offset": 9,
      "type": "<ALPHANUM>",
      "position": 1
    }
  ]
}

版權宣告

作者: ma_shoufeng(馬瘦風)

出處: CSDN 馬瘦風的部落格

您的支援是對博主的極大鼓勵, 感謝您的閱讀.

本文版權歸博主所有, 歡迎轉載, 但未經博主同意必須保留此段宣告, 且在文章頁面明顯位置給出原文連結, 否則博主保留追究相關人員法律責任的權利.