1. 程式人生 > >ElasticSearch實戰三(分詞和對映)

ElasticSearch實戰三(分詞和對映)

    ElasticSearch的文件對映機制(mapping)用於進行欄位的型別確認,將每一個欄位匹配為一種確定的資料型別。

1  ES欄位型別

    ① 基本欄位型別

    字串:text、keyword

        text預設為全文文字,keyword預設為非全文文字

    數字:long、integer、short、double、float

    日期:date

    邏輯:boolean

    ② 複雜資料型別

    物件型別:object

    陣列型別:array

    地理位置:geo_point,geo_shape

    我們在建立一個索引的時候,欄位並沒有明確說明屬於哪一個型別的資料,但是ES會根據預設的規則去匹配相應的資料型別的。下面的id,name,birthday,salary,set表示了不同型別的資料結構。

PUT /crm/user/1
{
  "id":1,
  "name":"gosaint",
  "birthday":"2018-11-03",
  "salary":1000.890,
  "sex":true
}

預設對映

檢視索引型別的對映配置:GET {indexName}/_mapping/{typeName}

ES在沒有配置Mapping的情況下新增文件,ES會嘗試對欄位型別進行猜測,並動態生成欄位和型別的對映關係。

JSON type

Field type

Boolean: true or false

"boolean"

Whole number: 123

"long"

Floating point: 123.45

"float"

String, valid date:"2014-09-15"

"date"

String: "foo bar"

"string"

    針對上述的例項,我們可以使用GET /crm/_mapping/user來檢視資料的資料型別;

    birthday:date

    id  : long

    name:text。全文文字,預設會分詞。

    salary:flaot

    sex :boolean

{
  "crm": {
    "mappings": {
      "user": {
        "properties": {
          "birthday": {
            "type": "date"
          },
          "id": {
            "type": "long"
          },
          "name": {
            "type": "text",
            "fields": {
              "keyword": {
                "type": "keyword",
                "ignore_above": 256
              }
            }
          },
          "salary": {
            "type": "float"
          },
          "sex": {
            "type": "boolean"
          }
        }
      }
    }
  }
}

簡單型別對映

type

型別:基本資料型別,integer,long,date,boolean,keyword,text...

enable

是否啟用:預設為true。 false:不能索引、不能搜尋過濾,僅在_source中儲存

boost

權重提升倍數:用於查詢時加權計算最終的得分。

format

格式:一般用於指定日期格式,如 yyyy-MM-dd HH:mm:ss.SSS

ignore_above

長度限制:長度大於該值的字串將不會被索引和儲存。

ignore_malformed

轉換錯誤忽略:true代表當格式轉換錯誤時,忽略該值,被忽略後不會被儲存和索引。

include_in_all

是否將該欄位值組合到_all中。

null_value

預設控制替換值。如空字串替換為”NULL”,空數字替換為-1

store

是否儲存:預設為false。true意義不大,因為_source中已有資料

index

索引模式:analyzed (索引並分詞,text預設模式), not_analyzed (索引不分詞,keyword預設模式),no(不索引)

analyzer

索引分詞器:索引建立時使用的分詞器,如ik_smart,ik_max_word,standard

search_analyzer

搜尋分詞器:搜尋該欄位的值時,傳入的查詢內容的分詞器。

fields

多欄位索引:當對該欄位需要使用多種索引模式時使用。

如:城市搜尋New York

"city": {

     "type": "text",

     "analyzer": "ik_smart",

     "fields": {

            "raw": {

                "type":  "keyword"

             }

     }

}

那麼以後搜尋過濾和排序就可以使用city.raw欄位名

自定義型別對映

    在上述的例項中,ES預設已經為相關的欄位指定型別。因此我們不可能改變原來欄位的型別。如我們不能去修改id的型別為integer。但是對於追加的欄位還是可以指定型別對映的。

① 針對單個型別的對映配置方式

POST {indexName}/{typeName}/_mapping
{

    "{typeName}": {

        "properties": {

            "id": {

                "type": "long"

            },

            "content": {

                "type": "text",

                "analyzer": "ik_smart",

                "search_analyzer": "ik_smart"

            }

        }

    }

}
POST /crm/user/_mapping
{
    "user": {
        "properties": {
            "id": {
                "type": "integer"
            },
           "name":{
             "type":"keyword"
           },
           "birthday":{
             "type":"text"
           },
           "salary":{
             "type":"double"
           },
           "sex":{
             "type":"boolean"
           }
        }
    }
}

看看響應結果:

{
  "error": {
    "root_cause": [
      {
        "type": "illegal_argument_exception",
        "reason": "mapper [name] of different type, current_type [text], merged_type [keyword]"
      }
    ],
    "type": "illegal_argument_exception",
    "reason": "mapper [name] of different type, current_type [text], merged_type [keyword]"
  },
  "status": 400
}

這恰好說明,原來的欄位對映存在,再次指定的時候就會失敗。如果要想重新指派,那麼就要刪除原來的索引庫。

刪除crm索引庫。DELETE /crm。然後建立crm PUT /crm。然後執行上述的自定義指派對映。

{
  "crm": {
    "mappings": {
      "user": {
        "_all": {
          "enabled": false
        },
        "dynamic_templates": [
          {
            "string_as_text": {
              "match": "*_text",
              "match_mapping_type": "string",
              "mapping": {
                "analyzer": "ik_max_word",
                "fields": {
                  "raw": {
                    "ignore_above": 256,
                    "type": "keyword"
                  }
                },
                "search_analyzer": "ik_max_word",
                "type": "text"
              }
            }
          },
          {
            "string_as_keyword": {
              "match_mapping_type": "string",
              "mapping": {
                "type": "keyword"
              }
            }
          }
        ],
        "properties": {
          "birthday": {
            "type": "text"
          },
          "id": {
            "type": "integer"
          },
          "name": {
            "type": "keyword"
          },
          "salary": {
            "type": "double"
          },
          "sex": {
            "type": "boolean"
          }
        }
      }
    }
  }
}

可以看到我們自定義對映成功啦。

② 同時對多個型別的對映配置方式(推薦)

PUT {indexName}

{

  "mappings": {

    "user": {

      "properties": {

        "id": {

          "type": "integer"

        },

        "info": {

          "type": "text",

          "analyzer": "ik_smart",

          "search_analyzer"

        }

      }

    },

    "dept": {

      "properties": {

        "id": {

          "type": "integer"

        },

        ....更多欄位對映配置

      }

    }

  }

}

5 全域性對映

    全域性對映可以通過動態模板和預設設定兩種方式實現。

    預設方式:_default_

索引下所有的型別對映配置會繼承_default_的配置,如:

PUT {indexName}
{
  "mappings": {
    "_default_": { 
      "_all": {
        "enabled": false
      }
    },
    "user": {}, 
    "dept": { 
      "_all": {
        "enabled": true
      }
    }
  }
}

    上例中:user和dept都會繼承_default_的配置,user型別的文件中將不會合並所有欄位到_all,而dept會。

動態模板:dynamic_templates

    注意:ES會預設把string型別的欄位對映為text型別(預設使用標準分詞器)和對應的keyword型別,如:

"name": {

     "type": "text",

     "fields": {

         "keyword": {

             "type": "keyword",

             "ignore_above": 256

          }

      }

}

    在實際應用場景中,一個物件的屬性中,需要全文檢索的欄位較少,大部分字串不需要分詞,因此,需要利用全域性模板覆蓋自帶的預設模板:

PUT _template/global_template  //建立名為global_template的模板

{

  "template":   "*",  //匹配所有索引庫

  "settings": { "number_of_shards": 1 }, //匹配到的索引庫只建立1個主分片

  "mappings": {

    "_default_": {

      "_all": { 

        "enabled": false //關閉所有型別的_all欄位

      },

      "dynamic_templates": [

        {

          "string_as_text": {

            "match_mapping_type": "string",//匹配型別string

            "match":   "*_text", //匹配欄位名字以_text結尾

            "mapping": {

              "type": "text",//將型別為string的欄位對映為text型別

              "analyzer": "ik_max_word",

              "search_analyzer": "ik_max_word",

              "fields": {

                "raw": {

                  "type":  "keyword",

                  "ignore_above": 256

                }

              }

            }

          }

        },

        {

          "string_as_keyword": { 

            "match_mapping_type": "string",//匹配型別string

            "mapping": {

              "type": "keyword"//將型別為string的欄位對映為keyword型別

             }

          }

        }

      ]

    }

  }}

說明:上例中定義了兩種動態對映模板string_as_text和string_as_keyword.

在實際的型別欄位對映時,會依次匹配:

①欄位自定義配置

②全域性dynamic_templates[string_as_text、string_as_keyword]、

③索引dynamic_templates[...]

④ES自帶的string型別對映,以最先匹配上的為準。

注意:索引庫在建立的時候會繼承當前最新的dynamic_templates,索引庫建立後,修改動態模板,無法應用到已存在的索引庫。

​​​​​​​6 最佳實踐

    對映的配置會影響到後續資料的索引過程,因此,在實際專案中應遵循如下順序規則:

    ① 配置全域性動態模板對映(覆蓋預設的string對映)

    ② 配置欄位對映(由於基本型別主要用於過濾和普通查詢,因此,欄位對映主要對需要全文檢索的欄位進行配置)

    ③ 建立、更新和刪除文件

    ④ 搜尋