1. 程式人生 > >Elasticsearch實踐(三):Mapping

Elasticsearch實踐(三):Mapping

版本:Elasticsearch 6.2.4。

Mapping類似於資料庫中的表結構定義,主要作用如下:

  • 定義Index下欄位名(Field Name)
  • 定義欄位的型別,比如數值型,字串型、布林型等
  • 定義倒排索引的相關配置,比如是否索引、記錄postion等

Mapping完整的內容可以分為四部分內容:

  • 欄位型別(Field datatypes)
  • 元欄位(Meta-Fields)
  • Mapping引數配置(Mapping parameters)
  • 動態Mapping(Dynamic Mapping)

自動Mapping

如果沒有手動設定Mapping,Elasticsearch預設會自動解析出型別,且每個欄位以第一次出現的為準。

下面我們先看一下Elasticsearch預設建立的Mapping是什麼樣的。

首先我們建立一個索引:

PUT /user/

查詢索引資訊:

GET /user

結果:

{
  "user": {
    "aliases": {},
    "mappings": {},
    "settings": {
      "index": {
        "creation_date": "1540044686190",
        "number_of_shards": "5",
        "number_of_replicas": "1",
        "uuid": "_K5b8w7jRiuthf7QeQZhdw",
        "version": {
          "created": "5060299"
        },
        "provided_name": "user"
      }
    }
  }
}

增加一條資料:

PUT /user/doc/1
{
  "name":"Allen Yer",
  "job":"php",
  "age":22
}

PUT /user/doc/2
{
  "name":"Allen Yer",
  "job":0,
  "age":22
}

查詢資料是否新增成功:

GET /user/doc/_count

結果:

{
  "count": 2,
  "_shards": {
    "total": 5,
    "successful": 5,
    "skipped": 0,
    "failed": 0
  }
}

count為2,說明新增成功。然後我們查詢下 mapping :

{
  "user": {
    "mappings": {
      "doc": {
        "properties": {
          "age": {
            "type": "long"
          },
          "job": {
            "type": "text",
            "fields": {
              "keyword": {
                "type": "keyword",
                "ignore_above": 256
              }
            }
          },
          "name": {
            "type": "text",
            "fields": {
              "keyword": {
                "type": "keyword",
                "ignore_above": 256
              }
            }
          }
        }
      }
    }
  }
}

發現自動為每個欄位設定了型別:

  • name: text型別,另外額外增加了name.keyword欄位,keyword型別;
  • job:text型別,另外額外增加了job.keyword欄位,keyword型別;雖然第二次資料新增是數字型別,但還是以第一次為主;
  • age:long型別。

大家可以把索引刪掉,將新增資料調整為先新增第2條,再新增第一條,發現報錯了:

DELETE /user

PUT /user/doc/2
{
  "name":"Allen Yer",
  "job":0,
  "age":22
}

PUT /user/doc/1
{
  "name":"Allen Yer",
  "job":"php",
  "age":22
}

報錯:

{
  "error": {
    "root_cause": [
      {
        "type": "mapper_parsing_exception",
        "reason": "failed to parse [job]"
      }
    ],
    "type": "mapper_parsing_exception",
    "reason": "failed to parse [job]",
    "caused_by": {
      "type": "number_format_exception",
      "reason": "For input string: \"php\""
    }
  },
  "status": 400
}

也能說明以第一次為主以欄位第一次的值型別為準。這也說明了預設建立mapping可能不是我們想要的,這就需要手動建立mapping,好處有:

  • 提前指定欄位(通過設定甚至可以達到禁止自動增加欄位的效果)
  • 合理設定欄位型別,防止分詞過多或者解析不合理。分詞過大會導致磁碟空間佔用大。

手動建立mapping

這次我們刪掉mapping,並手動建立一個:

DELETE /user

PUT /user/
{
    "mappings": {
      "doc": {
        "properties": {
          "name": {
            "type": "text",
            "fields": {
              "keyword": {
                "type": "keyword",
                "ignore_above": 256
              }
            }
          },
          "age": {
            "type": "long",
            "index": false
          },
          "job": {
            "type": "keyword"
          },
          "intro":{
            "type":"text"
          },
          "create_time": {
            "type": "date", 
            "format": "epoch_second"
        }
        }
     }
  }
}

欄位型別說明:

  • name:text型別,會進行分詞,支援模糊檢索。
  • name.keyword : 這相當於是嵌套了一個欄位,keyword型別,只能精確匹配,不支援分詞。超過256字元長度不索引,也就沒法搜尋到。
  • age:long型別,支援精確匹配。
  • job:keyword型別,只能精確匹配,不支援分詞。
  • intro:text型別,會進行分詞,支援模糊檢索。
  • create_time:date型別,支援10位時間戳。

注意:mapping生成後是不允許修改(包括刪除)的。所以需要提前合理的的定義mapping。

欄位型別

Elasticsearch支援文件中欄位的許多不同資料型別:

普通資料型別

字串型別

textkeyword2種 。其中 text 支援分詞,用於全文搜尋;keyword 不支援分詞,用於聚合和排序。在舊的ES裡這兩個型別由string表示。

如果安裝了IK分詞外掛,我們可以為text型別指定IK分詞器。一般來說,對於字串型別,如果:

1) 模糊搜尋+精確匹配,一般是name或者title欄位:

"name": {
        "type": "text",
        "analyzer": "ik_smart",
        "fields": {
          "keyword": {
            "type": "keyword",
            "ignore_above": 256
          }
        }
      }

2) 模糊搜尋,一般是內容詳情欄位:

"content": {
        "type": "text",
        "analyzer": "ik_smart"
      }

3) 精確匹配:

"name": {
        "type": "keyword"
      }

4) 不需要索引:

"url": {
        "type": "keyword",
        "index": false
      }

數字型別

支援 long,integer,short,byte,double,float,half_float,scaled_float。具體說明如下:

  • long
    帶符號的64位整數,其最小值為-2^63,最大值為(2^63)-1

  • integer
    帶符號的32位整數,其最小值為-2^31,最大值為(23^1)-1

  • short
    帶符號的16位整數,其最小值為-32,768,最大值為32,767。

  • byte
    帶符號的8位整數,其最小值為-128,最大值為127。

  • double
    雙精度64位IEEE 754浮點數。

  • float
    單精度32位IEEE 754浮點數。

  • half_float
    半精度16位IEEE 754浮點數。

  • scaled_float
    縮放型別的的浮點數。需同時配置縮放因子(scaling_factor)一起使用。

對於整數型別(byte,short,integer和long)而言,我們應該選擇這是足以使用的最小的型別。這將有助於索引和搜尋更有效。

對於浮點型別(float、half_float和scaled_float),-0.0+0.0是不同的值,使用term查詢查詢-0.0不會匹配+0.0,同樣range查詢中上邊界是-0.0不會匹配+0.0,下邊界是+0.0不會匹配-0.0

其中scaled_float,比如價格只需要精確到分,price57.34的欄位縮放因子為100,存起來就是5734。優先考慮使用帶縮放因子的scaled_float浮點型別。

示例:

PUT my_index
{
  "mappings": {
    "_doc": {
      "properties": {
        "status": {
          "type": "byte"
        },
        "year": {
          "type": "short"
        },
        "id": {
          "type": "long"
        },
        "price": {
          "type": "scaled_float",
          "scaling_factor": 100
        }
      }
    }
  }
}

日期型別

型別為 date

JSON本身是沒有日期型別的,因此Elasticsearch中的日期可以是:

  • 包含格式化日期的字串。
  • 一個13位long型別表示的毫秒時間戳( milliseconds-since-the-epoch)。
  • 一個integer型別表示的10位普通時間戳(seconds-since-the-epoch)。

在Elasticsearch內部,日期型別會被轉換為UTC(如果指定了時區)並存儲為long型別表示的毫秒時間戳。

日期型別可以使用使用format自定義,預設預設值:"strict_date_optional_time||epoch_millis"

"postdate": {
      "type": "date",
      "format": "strict_date_optional_time||epoch_millis"
    }

format 有很多內建型別,這裡列舉部分說明:

  • strict_date_optional_time, date_optional_time
    通用的ISO日期格式,其中日期部分是必需的,時間部分是可選的。例如 "2015-01-01"或"2015/01/01 12:10:30"。
  • epoch_millis
    13位毫秒時間戳
  • epoch_second
    10位普通時間戳

其中strict_開頭的表示嚴格的日期格式,這意味著,年、月、日部分必須具有前置0。

當然也可以自定義日期格式,例如:

"postdate":{
      "type":"date",
      "format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd"
    }

注意:如果新文件的欄位的值與format裡設定的型別不相容,ES會返回失敗。示例:

PUT my_index
{
  "mappings": {
    "_doc": {
      "properties": {
        "date": {
          "type": "date",
          "format":"epoch_millis"
        }
      }
    }
  }
}

PUT my_index/_doc/1
{
  "date":1543151405000
}
PUT my_index/_doc/2
{
  "date":1543151405
}
PUT my_index/_doc/3
{
  "date":"2018-11-25 21:10:43"
}
GET my_index/_doc/_search

第3條資料插入失敗,因為只接受長整數的時間戳,字串型別的日期是不匹配的。第2條的值只有10位數,雖然值是不正確的,但是在epoch_millis的取值範圍內,所以也是成功的。

布林型別

型別為 boolean

二進位制型別

型別為 binary

範圍型別

integer_range,float_range,long_range,double_range,date_range

複雜型別

  • 陣列資料型別
    在ElasticSearch中,沒有專門的陣列(Array)資料型別,但是,在預設情況下,任意一個欄位都可以包含0或多個值,這意味著每個欄位預設都是陣列型別,只不過,陣列型別的各個元素值的資料型別必須相同。在ElasticSearch中,陣列是開箱即用的(out of box),不需要進行任何配置,就可以直接使用。,例如:

字元型陣列: [ "one", "two" ]
整型陣列:[ 1, 2 ]
陣列型陣列:[ 1, [ 2, 3 ]] 等價於[ 1, 2, 3 ]

  • 物件資料型別
    object 對於單個JSON物件。JSON天生具有層級關係,文件可以包含巢狀的物件。

  • 巢狀資料型別
    nested 對於JSON物件的陣列

Geo資料型別

  • 地理點資料型別
    geo_point 對於緯度/經度點

  • Geo-Shape資料型別
    geo_shape 對於像多邊形這樣的複雜形狀

專用資料型別

  • IP資料型別
    ip 用於IPv4和IPv6地址

  • 完成資料型別
    completion 提供自動完成的建議

  • 令牌計數資料型別
    token_count 計算字串中的標記數

  • mapper-murmur3
    murmur3 在索引時計算值的雜湊值並將它們儲存在索引中

  • 過濾器型別
    接受來自query-dsl的查詢

  • join 資料型別
    為同一索引中的文件定義父/子關係

多欄位

為不同目的以不同方式索引相同欄位通常很有用。例如,string可以將欄位對映為text用於全文搜尋的keyword欄位,以及用於排序或聚合的欄位。或者,您可以使用standard分析儀, english分析儀和 french分析儀索引文字欄位。

元欄位

_all

該欄位用於在沒有指定具體欄位的情況下進行模糊搜尋,可以搜尋全部欄位的內容。

原理是將所有欄位的內容視為字串,拼在一起放在一個_all欄位上,但這個欄位預設是不被儲存的,可以被搜尋。在query_stringsimple_query_string查詢(Kibana搜尋框用的這種查詢方式)預設也是查詢_all欄位。

6.x 版本被預設關閉。

相關設定:

PUT my_index
{
  "mappings": {
    "my_type": {
      "_all": {
        "enabled": true,
        "store": false
      },
      "properties": {}
    }
  },
  "settings": {
    "index.query.default_field": "_all" 
  }
}

上述配置在5.x版本是預設配置:

  • 預設開啟 _all 欄位
  • 預設不儲存 _all 欄位
  • 預設搜尋 _all 欄位

如果從CPU效能及磁碟空間考慮,可以考慮可以完全禁用或基於每個欄位自定義_all欄位。

假設_all欄位被禁用,則URI搜尋請求、 query_stringsimple_query_string查詢將無法將其用於查詢。我們可以將它們配置為其他欄位:通過定義 index.query.default_field 屬性。

_source

這個欄位用於儲存原始的JSON文件內容,本身不會被索引,但是搜尋的時候被返回。如果沒有該欄位,雖然還能正常搜尋,但是返回的內容不知道對應的是什麼。

示例:

GET /user/doc/_search?q=name

結果:

{
  "took": 4,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": 1,
    "max_score": 0.2876821,
    "hits": [
      {
        "_index": "user",
        "_type": "doc",
        "_id": "1",
        "_score": 0.2876821,
        "_source": {
          "name": "this is test name",
          "age": 22,
          "job": "java",
          "intro": "the intro can not be searched by singal",
          "intro2": "去朝陽公園",
          "create_time": 1540047542
        }
      }
    ]
  }
}

搜尋結果就包含_source欄位,儲存的是原始文件內容。如果被禁用,只知道有匹配內容,但是無法知道返回的是什麼。所以需要謹慎關閉該欄位。

如果想禁用該欄位,可以在建立Mapping的時候,設定_:

{
  "mappings": {
    "_doc": {
      "_source": {
        "enabled": false
      }
    }
  }
}

_type

ElasticSearch裡面有 index 和 type 的概念:index稱為索引,type為文件型別,一個index下面有多個type,每個type的欄位可以不一樣。這類似於關係型資料庫的 database 和 table 的概念。

但是,ES中不同type下名稱相同的filed最終在Lucene中的處理方式是一樣的。所以後來ElasticSearch團隊想去掉type,於是在6.x版本為了向下相容,一個index只允許有一個type。

該欄位再在6.0.0中棄用。在Elasticsearch 6.x 版本中建立的索引只能包含單個type。在5.x中建立的含有多個type的索引將繼續像以前一樣在Elasticsearch 6.x中執行。type 將在Elasticsearch 7.0.0中完全刪除。

參考

相關推薦

Elasticsearch實踐Mapping

版本:Elasticsearch 6.2.4。 Mapping類似於資料庫中的表結構定義,主要作用如下: 定義Index下欄位名(Field Name) 定義欄位的型別,比如數值型,字串型、布林型等 定義倒排索引的相關配置,比如是否索引、記錄postion等 Mapping完整的內容可以分為四部分內容

Elasticsearch實踐搜尋

本文以 Elasticsearch 6.2.4為例。 經過前面的基礎入門,我們對ES的基本操作也會了。現在來學習ES最強大的部分:全文檢索。 準備工作 批量匯入資料 先需要準備點資料,然後匯入: wget https://raw.githubusercontent.com/elastic/

Elasticsearch實踐IK分詞

完成 詞語 char 1.2 prop tokenize 字母 發生 odi 環境:Elasticsearch 6.2.4 + Kibana 6.2.4 + ik 6.2.4 Elasticsearch默認也能對中文進行分詞。 我們先來看看自帶的中文分詞效果: curl

Elasticsearch實戰高階搜尋中文+拼音+首字母+簡繁轉換+補全

1、中文搜尋、英文搜尋、中英混搜  如:“紫光股份”,“紫光gufen” 2、全拼搜尋、首字母搜尋、中文+全拼、中文+首字母混搜   如:“ziguanggufen”,“紫光gufen”,“紫光gf”,“zggf”,“ziguanggf”等等組合 3、簡繁搜尋 4.關鍵

C++實踐C++實現加密演算法AES

本篇主要講2015年寫的加密演算法。包括:AES,AES-CMAC,HMAC,基於RSA與HMAC的數字簽名演算法。當時大概寫了2天。哈哈! AES演算法 AES是一個對稱加密標準,用以取代DES的商業應用。其分組長度為128位,192位或者256位。

TensorFlow學習實踐使用TFRecord格式資料和tf.estimator API進行模型訓練和預測

本文以mnist為例,介紹如何使用TFRecord格式資料和tf.estimator API進行模型訓練和預測。 參考: 目錄 一、資料輸入 def input_fn(filenames, training): dataset = tf.dat

.Net微服務實踐Ocelot配置路由和請求聚合

[TOC] 在上篇[.Net微服務實踐(二):Ocelot介紹和快速開始](https://www.cnblogs.com/lcyhjx/p/12649936.html)中我們介紹了Ocelot,建立了一個Ocelot Hello World程式,接下來,我們會介紹Oclot的主要特性**路由**和另外一個

ElasticSearch實踐系列探索資料

前言 經過前兩篇文章得實踐,我們已經瞭解了ElasticSearch的基礎知識,本篇文章讓我來操作一些更真實的資料集。我們可以利用www.json-generator.com/生成如下的文件結構: { "account_number": 1, "balance": 39225,

MySQL的JOINJOIN優化實踐之內循環的次數

ted www str 連接 pri 記錄 font 語句 style 這篇博文講述如何優化內循環的次數。內循環的次數受驅動表的記錄數所影響,驅動表記錄數越多,內循環就越多,連接效率就越低下,所以盡量用小表驅動大表。先插入測試數據。 CREATE TABLE t1

ElasticSearchJava操作ElasticSearch索引之CRUD

transport delete end std testin python網絡 search ava socket 1 package com.gxy.ESChap01; 2 3 import java.net.InetAddress; 4 impor

eShopOnContainers學習系列RabbitMQ訊息匯流排實踐

今天研究了下eShopOnContainers裡的RabbitMQ的使用,在專案裡是以封裝成訊息匯流排的方式使用的,但是仍然是以其釋出、訂閱兩個方法作為基礎封裝的,我們今天就來實際使用一下。 為了簡單起見,就在同一個API專案裡實現釋出訂閱。 新建API專案 RabbitMQ_Bus_Test

eShopOnContainers學習系列RabbitMQ消息總線實踐

bytes 變量名 fault invalid available 通信 make 中新 down 今天研究了下eShopOnContainers裏的RabbitMQ的使用,在項目裏是以封裝成消息總線的方式使用的,但是仍然是以其發布、訂閱兩個方法作為基礎封裝的,我們今天就來

Elasticsearch 通關教程 索引別名Aliases問題

業務問題 業務需求是不斷變化迭代的,也許我們之前寫的某個業務邏輯在下個版本就變化了,我們可能需要修改原來的設計,例如資料庫可能需要新增一個欄位或刪減一個欄位,而在搜尋中也會發生這件事,即使你認為現在的索引設計已經很完美了,在生產環境中,還是有可能需要做一些修改的,需要新增對映欄位或者需要修改欄位型別等等。

ElasticSearch學習總結查詢總結

本文主要對Elasticsearch中查詢相關的知識做一個簡單的總結,內容主要包括查詢的評分機制,查詢改寫,過濾器,以及對常見的查詢做一個簡單的分類 1. 評分機制 在Lucense中預設使用TF/IDF演算法對文件進行評分,該演算法已經在前文做了簡單的介紹,這裡主要總結下什麼樣的因

ElasticSearch原始碼解析索引建立

我們先來看看索引建立的事例程式碼: Directory directory = FSDirectory.getDirectory("/tmp/testindex"); // Use standard analyzer Analyzer analyzer = new

ELKElasticsearch如何安裝及相關外掛介紹?

安裝步驟 系統準備: 作業系統:CentOS6.4 64bit 軟體版本:JDK8.60 , Elasticsearch1.7.1 具體軟體名稱:jdk-8u60-linux-x64.tar.gz , elasticsearch-1.7.1.tar.

Spring Boot 實踐折騰記三板斧,Spring Boot下使用Mybatis

你要搞清楚自己人生的劇本:不是你父母的續集,不是你子女的前傳,更不是你朋友的外篇。對待生命你不妨大膽冒險一點,因為好歹你要失去它。——源自尼采 開始前… 上面的金句是被轉載很多的一句話,Spring Boot也有自己的舞臺,只是這個舞臺還沒有大量展開

深度學習實踐操作—從小白到大白Linux遠端控制

深度學習實踐操作—從小白到大白 目錄 三. Linux遠端控制 在具體使用時,特別是實驗室或者工作時多人使用同一臺伺服器,一般通過本機遠端控制。 本機是Linux系統,使用ssl指令即可:ssh –l 使用者名稱 IP地址 ssh

Spring Boot 2 快速教程WebFlux Restful CRUD 實踐

摘要: 原創出處 https://www.bysocket.com 「公眾號:泥瓦匠BYSocket 」歡迎關注和轉載,保留摘要,

ElasticStack學習ElasticSearch基本概念

1、文件   1)ElasticSearch是面向文件的,文件是所有可搜尋資料的最小單位。例如:     a)日誌檔案中的日誌項;     b)一張唱片的詳細資訊;     c)一篇文章中的具體內容;    2)在ElasticSearch中,文件會被序列化成Json格式:     a)Json物