日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

elasticsearch索引和映射

發(fā)布時間:2024/9/5 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 elasticsearch索引和映射 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

目錄

  • 1. elasticsearch如何實現(xiàn)搜索
    • 1.1 搜索實例
    • 1.2 es中數(shù)據(jù)的類型
    • 1.3 倒排索引
    • 1.4 分析與分析器
      • 1.4.1 什么是分析器
      • 1.4.2 內(nèi)置分析器種類
      • 1.4.3 分析行為(開篇實例解答)
      • 1.4.4 測試分析器
      • 1.4.5 指定分析器
    • 1.5 映射
      • 1.5.1 簡單核心域類型
      • 1.5.2 復雜核心域類型
  • 2. 索引
    • 2.1 什么是索引
    • 2.2 創(chuàng)建一個默認配置的索引
    • 2.3 索引的設置(settings部分)
    • 2.4 索引的映射配置(mappings部分)
      • 2.4.1 映射寫法
      • 2.4.2 類型
      • 2.4.3 根對象
      • 2.4.4 動態(tài)映射
      • 2.4.5 自定義動態(tài)映射
      • 2.4.6 缺省映射
    • 2.5 索引的管理
      • 2.5.1 創(chuàng)建索引
      • 2.5.2 查看索引
      • 2.5.3 刪除索引
      • 2.5.4 重構(gòu)索引

1. elasticsearch如何實現(xiàn)搜索

我們使用sql數(shù)據(jù)庫的時候,要先創(chuàng)建數(shù)據(jù)庫,然后創(chuàng)建表,之后才可以將數(shù)據(jù)存入到表中,這個表規(guī)定了數(shù)據(jù)的構(gòu)成結(jié)構(gòu)。雖然elasticsearch是一個無模式的搜索引擎并且可以自動匹配數(shù)據(jù)的結(jié)構(gòu)(ES 會盡量根據(jù) JSON 源數(shù)據(jù)的基礎類型猜測你想要的字段類型映射),但是我們認為人為定義和控制數(shù)據(jù)結(jié)構(gòu)是更好的方式。所以我們有必要學習如何創(chuàng)建索引和如何創(chuàng)建映射。

1.1 搜索實例

在mysql中我們查詢created_at = '2014-09-15'那么該created_at字段只有是2014-09-15和不是兩種情況,但是在elsaticsearch中則很有趣,看下下面的例子

索引中有12條推文,其中只有一條包含日期 2014-09-15 ,但是看一看下面查詢命中的 總數(shù) (total):

GET /_search?q=2014 # 12 results GET /_search?q=2014-09-15 # 12 results ! GET /_search?q=date:2014-09-15 # 1 result GET /_search?q=date:2014 # 0 results !

分析:

  • 第一個和第二個搜索是全文搜索,起作用的是 _all字段 ,這里都返回了12條推文,但是我們提到了只有一條包含了日期 2014-09-15,為什么12條數(shù)據(jù)都能匹配?

  • 第三和第四條數(shù)據(jù)時在 data字段 搜索,不難理解,第三條數(shù)據(jù)一條命中,第四條只是個年份,不可能有匹配項。

為什么會出現(xiàn)上面的結(jié)果呢,全文搜索好像有點不一般啊,推測起來,這可能是數(shù)據(jù)在 _all 字段與 date 字段的索引方式不同。帶著這個疑問我們一起分析下。

可以查看下索引的類型映射

GET /gb/_mapping/tweet

結(jié)果如下

{"gb": {"mappings": {"tweet": {"properties": {"date": {"type": "date","format": "strict_date_optional_time||epoch_millis"},"name": {"type": "string"},"tweet": {"type": "string"},"user_id": {"type": "long"}}}}} }

盡管我們沒有定義該索引的映射,但是es動態(tài)為我們產(chǎn)生了一個映射,這個響應告訴我們 date 字段被認為是 date 類型的。由于 _all 是默認字段,所以沒有提及它。但是我們知道 _all 字段是 string 類型的。所以 date 字段和 string 字段 索引方式不同,數(shù)據(jù)類型不同,因此搜索結(jié)果也不一樣,但這只是表象,深層次原因呢?

1.2 es中數(shù)據(jù)的類型

Elasticsearch 中的數(shù)據(jù)可以概括的分為兩類:『精確值』和 『全文』。

?『精確值』 如它們聽起來那樣精確。例如日期或者用戶 ID,但字符串也可以表示精確值,例如用戶名或郵箱地址。對于精確值來講,Foo 和 foo 是不同的,2014 和 2014-09-15 也是不同的。

精確值很容易查詢。結(jié)果是二進制的:要么匹配查詢,要么不匹配。這種查詢很容易用 SQL 表示:

WHERE name = "John Smith"AND user_id = 2AND date > "2014-09-15"

?『全文』 是指文本數(shù)據(jù)(通常以人類容易識別的語言書寫),例如一個推文的內(nèi)容或一封郵件的內(nèi)容。

查詢?nèi)臄?shù)據(jù)要微妙的多。我們問的不只是“這個文檔匹配查詢嗎”,而是“該文檔匹配查詢的程度有多大?”。

我們很少對全文類型的域做精確匹配。相反,我們希望在文本類型的域中搜索。不僅如此,我們還希望搜索能夠理解我們的 意圖

  • 搜索 UK ,會返回包含 United Kindom 的文檔。
  • 搜索 jump ,會匹配 jumped , jumps , jumping ,甚至是 leap 。
  • 搜索 johnny walker 會匹配 Johnnie Walker , johnnie depp 應該匹配 Johnny Depp 。
  • fox news hunting 應該返回福克斯新聞( Foxs News )中關(guān)于狩獵的故事,同時, fox hunting news 應該返回關(guān)于獵狐的故事。

es是如何做到以上的想法的呢?

Elasticsearch 首先會 分析文檔,之后根據(jù)結(jié)果創(chuàng)建 倒排索引 ,接下來一起討論分析過程和倒排索引

1.3 倒排索引

一個倒排索引由文檔中所有不重復詞的列表構(gòu)成,對于其中每個詞,有一個包含它的文檔列表。

例如,假設我們有兩個文檔,每個文檔的 content 域包含如下內(nèi)容:

The quick brown fox jumped over the lazy dog Quick brown foxes leap over lazy dogs in summer

為了創(chuàng)建倒排索引,我們首先將每個文檔的 content 域拆分成單獨的 詞(我們稱它為 詞條 或 tokens ),創(chuàng)建一個包含所有不重復詞條的排序列表,然后列出每個詞條出現(xiàn)在哪個文檔。結(jié)果如下所示:

Term Doc_1 Doc_2 ------------------------- Quick | | X The | X | brown | X | X dog | X | dogs | | X fox | X | foxes | | X in | | X jumped | X | lazy | X | X leap | | X over | X | X quick | X | summer | | X the | X | ------------------------

現(xiàn)在,如果我們想搜索 quick brown ,我們只需要查找包含每個詞條的文檔:

Term Doc_1 Doc_2 ------------------------- brown | X | X quick | X | ------------------------ Total | 2 | 1

兩個文檔都匹配,但是第一個文檔比第二個匹配度更高。如果我們使用僅計算匹配詞條數(shù)量的簡單 相似性算法 ,那么,我們可以說,對于我們查詢的相關(guān)性來講,第一個文檔比第二個文檔更佳。

但是,我們目前的倒排索引有一些問題:

  • Quick 和 quick 以獨立的詞條出現(xiàn),然而用戶可能認為它們是相同的詞。
  • fox 和 foxes 非常相似, 就像 dog 和 dogs ;他們有相同的詞根。
  • jumped 和 leap, 盡管沒有相同的詞根,但他們的意思很相近。他們是同義詞。

使用前面的索引搜索 +Quick +fox 不會得到任何匹配文檔。(記住,+ 前綴表明這個詞必須存在。)只有同時出現(xiàn) Quick 和 fox 的文檔才滿足這個查詢條件,但是第一個文檔包含 quick fox ,第二個文檔包含 Quick foxes 。

我們的用戶可以合理的期望兩個文檔與查詢匹配。我們可以做的更好。

如果我們將詞條規(guī)范為標準模式,那么我們可以找到與用戶搜索的詞條不完全一致,但具有足夠相關(guān)性的文檔。例如:

  • Quick 可以小寫化為 quick 。
  • foxes 可以 詞干提取 --變?yōu)樵~根的格式-- 為 fox 。類似的, dogs 可以為提取為 dog 。
  • jumped 和 leap 是同義詞,可以索引為相同的單詞 jump 。
    現(xiàn)在索引看上去像這樣:
Term Doc_1 Doc_2 ------------------------- brown | X | X dog | X | X fox | X | X in | | X jump | X | X lazy | X | X over | X | X quick | X | X summer | | X the | X | X ------------------------

這還遠遠不夠。我們搜索 +Quick +fox 仍然 會失敗,因為在我們的索引中,已經(jīng)沒有 Quick 了。但是,如果我們對搜索的字符串使用與 content 域相同的標準化規(guī)則,查詢字符串就會變成查詢 +quick +fox ,這樣兩個文檔都會匹配!

注意:這非常重要。我們要用相同標準處理兩部分的數(shù)據(jù) 查詢字符串索引文本 ,你只能搜索在索引中出現(xiàn)的詞條,所以索引文本和查詢字符串必須標準化為相同的格式。

1.4 分析與分析器

1.4.1 什么是分析器

首先,將一塊文本分成適合于倒排索引的獨立的 詞條 ,
之后,將這些詞條統(tǒng)一化為標準格式以提高它們的“可搜索性”,或者 recall
分析器執(zhí)行上面的工作。 分析器 實際上是將三個功能封裝到了一個包里

  • 字符過濾器

首先,字符串按順序通過每個 字符過濾器 。字符過濾器 用來 整理 一個尚未被分詞的字符串。例如,如果我們的文本是HTML格式的,它會包含像 <p> 或者 <div> 這樣的HTML標簽,這些標簽是我們不想索引的。我們可以使用 html清除 字符過濾器 來移除掉所有的HTML標簽,并且像把 &Aacute; 轉(zhuǎn)換為相對應的Unicode字符 á 這樣,轉(zhuǎn)換HTML實體。

一個分析器可能有0個或者多個字符過濾器。

  • 分詞器

其次,字符串被 分詞器 分為單個的詞條。 分詞器把字符串分解成單個詞條或者詞匯單元。 標準 分析器 把一個字符串根據(jù)單詞邊界分解成單個詞條,并且移除掉大部分的標點符號,然而還有其他不同行為的分詞器存在。

例如, 關(guān)鍵詞 分詞器 完整地輸出 接收到的同樣的字符串,并不做任何分詞。 空格 分詞器 只根據(jù)空格分割文本 。 正則 分詞器 根據(jù)匹配正則表達式來分割文本 。

一個分析器 必須 有一個唯一的分詞器。

  • 詞單元過濾器

最后,詞條按順序通過每個 token 過濾器 。這個過程可能會改變詞條(例如,小寫化 Quick ),刪除詞條(例如, 像 a,and,the 等無用詞),或者增加詞條(例如,像 jump 和 leap 這種同義詞)。

Elasticsearch提供了開箱即用的字符過濾器、分詞器和詞單元過濾器。 這些可以組合起來形成自定義的分析器以用于不同的目的。

1.4.2 內(nèi)置分析器種類

但是, Elasticsearch還附帶了可以直接使用的預包裝的分析器。 接下來我們會列出最重要的分析器。為了證明它們的差異,我們看看每個分析器會從下面的字符串得到哪些詞條:

"Set the shape to semi-transparent by calling set_trans(5)"
  • 標準分析器

標準分析器是Elasticsearch默認使用的分析器。它是分析各種語言文本最常用的選擇。它根據(jù) Unicode 聯(lián)盟 定義的 單詞邊界 劃分文本。刪除絕大部分標點。最后,將詞條小寫。它會產(chǎn)生

set, the, shape, to, semi, transparent, by, calling, set_trans, 5
  • 簡單分析器

簡單分析器在任何不是字母的地方分隔文本,將詞條小寫。它會產(chǎn)生

set, the, shape, to, semi, transparent, by, calling, set, trans
  • 空格分析器

空格分析器在空格的地方劃分文本。它會產(chǎn)生

Set, the, shape, to, semi-transparent, by, calling, set_trans(5)
  • 語言分析器

特定語言分析器可用于 很多語言。它們可以考慮指定語言的特點。例如, 英語 分析器附帶了一組英語無用詞(常用單詞,例如 and 或者 the ,它們對相關(guān)性沒有多少影響),它們會被刪除。 由于理解英語語法的規(guī)則,這個分詞器可以提取英語單詞的 詞干 。

英語 分詞器會產(chǎn)生下面的詞條:

set, shape, semi, transpar, call, set_tran, 5

注意看 transparent、 calling 和 set_trans 已經(jīng)變?yōu)樵~根格式。

1.4.3 分析行為(開篇實例解答)

當我們 索引 一個文檔,它的全文域被分析成詞條以用來創(chuàng)建倒排索引。 但是,當我們在全文域 搜索 的時候,我們需要將查詢字符串通過 相同的分析過程 ,以保證我們搜索的詞條格式與索引中的詞條格式一致。

全文查詢,理解每個域是如何定義的,因此它們可以做 正確的事:

  • 當你查詢一個 全文 域時, 會對查詢字符串應用相同的分析器,以產(chǎn)生正確的搜索詞條列表。
  • 當你查詢一個 精確值 域時,不會分析查詢字符串, 而是搜索你指定的精確值。

現(xiàn)在你可以理解在 開始章節(jié) 的查詢?yōu)槭裁捶祷啬菢拥慕Y(jié)果:

  • date 域包含一個精確值:單獨的詞條 2014-09-15。
  • _all 域是一個全文域,所以分詞進程將日期(2014-09-15)轉(zhuǎn)化為三個詞條: 2014, 09, 和 15。
    當我們在 _all 域查詢 2014,它匹配所有的12條推文,因為它們都含有 2014 :
GET /_search?q=2014 # 12 results

當我們在 _all 域查詢 2014-09-15,它首先分析查詢字符串,產(chǎn)生匹配 2014, 09, 或 15 中 任意 詞條的查詢。這也會匹配所有12條推文,因為它們都含有 2014 :

GET /_search?q=2014-09-15 # 12 results !

當我們在 date 域查詢 2014-09-15,它尋找 精確 日期,只找到一個推文:

GET /_search?q=date:2014-09-15 # 1 result

當我們在 date 域查詢 2014,它找不到任何文檔,因為沒有文檔含有這個精確日志:

GET /_search?q=date:2014 # 0 results !

1.4.4 測試分析器

可以使用 analyze API 來看文本是如何被分析的。在消息體里,指定分析器和要分析的文本:

GET /_analyze {"analyzer": "standard","text": "Text to analyze" }

結(jié)果

{"tokens": [{"token": "text","start_offset": 0,"end_offset": 4,"type": "<ALPHANUM>","position": 1},{"token": "to","start_offset": 5,"end_offset": 7,"type": "<ALPHANUM>","position": 2},{"token": "analyze","start_offset": 8,"end_offset": 15,"type": "<ALPHANUM>","position": 3}] }

token 是實際存儲到索引中的詞條。 position 指明詞條在原始文本中出現(xiàn)的位置。 start_offset 和 end_offset 指明字符在原始字符串中的位置。

1.4.5 指定分析器

當Elasticsearch在你的文檔中檢測到一個新的字符串域 ,它會自動設置其為一個全文 字符串 域,使用 標準 分析器對它進行分析。

你不希望總是這樣。可能你想使用一個不同的分析器,適用于你的數(shù)據(jù)使用的語言。有時候你想要一個字符串域就是一個字符串域--不使用分析,直接索引你傳入的精確值,例如用戶ID或者一個內(nèi)部的狀態(tài)域或標簽。

要做到指定數(shù)據(jù)類型和指定鎖使用的分析器,我們必須手動指定這些域的映射。關(guān)于如何配置和指定分析器,將在索引的構(gòu)建中講解

1.5 映射

上面已經(jīng)知道了倒排索引,分析和分析器內(nèi)容,那么如何才能夠是es實現(xiàn)以上特性呢,就是編寫映射規(guī)則,我們配置映射的時候會規(guī)定數(shù)據(jù)的類型、是否使用分析器、使用何種分析器等內(nèi)容。

為了能夠?qū)r間域視為時間,數(shù)字域視為數(shù)字,字符串域視為全文或精確值字符串, Elasticsearch 需要知道每個域中數(shù)據(jù)的類型。映射定義了類型中的域,每個域的數(shù)據(jù)類型,以及Elasticsearch如何處理這些域。映射也用于配置與類型有關(guān)的元數(shù)據(jù)。我們這里先了解下映射的概念,下一章節(jié)會講解如何編寫映射。

1.5.1 簡單核心域類型

簡單域類型:

  • 字符串: string
  • 整數(shù) : byte, short, integer, long
  • 浮點數(shù): float, double
  • 布爾型: boolean
  • 日期: date

如果沒有定義數(shù)據(jù)的類型,也沒有使用定義動態(tài)映射規(guī)則,那么會通過JSON中基本數(shù)據(jù)類型,嘗試猜測域類型,使用如下規(guī)則:

JSON type域 type
布爾型: true 或者 falseboolean
整數(shù): 123long
浮點數(shù): 123.45double
字符串,有效日期: 2014-09-15date
字符串: foo barstring

1.5.2 復雜核心域類型

除了簡單標量數(shù)據(jù)類型, JSON 還有 null 值,數(shù)組,和對象,這些 Elasticsearch 都是支持的。

  • 多值域

對于數(shù)組,沒有特殊的映射需求,在es中沒有專門的數(shù)組類型。任何域都可以包含0、1或者多個值,就像全文域分析得到多個詞條。

數(shù)組中所有的值必須是相同數(shù)據(jù)類型的 。你不能將日期和字符串混在一起。如果你通過索引數(shù)組來創(chuàng)建新的域,Elasticsearch 會用數(shù)組中第一個值的數(shù)據(jù)類型作為這個域的 類型 。

數(shù)據(jù):

{ "tag": [ "search", "nosql" ]}
  • 空域

當然,數(shù)組可以為空。 這相當于存在零值。 事實上,在 Lucene 中是不能存儲 null 值的,所以我們認為存在 null 值的域為空域。

下面三種域被認為是空的,它們將不會被索引:

"null_value": null, "empty_array": [], "array_with_null_value": [ null ]
  • 多層級對象

數(shù)據(jù):

{"tweet": "Elasticsearch is very flexible","user": {"id": "@johnsmith","gender": "male","age": 26,"name": {"full": "John Smith","first": "John","last": "Smith"}} }

映射:

{"gb": {"tweet": { "properties": {"tweet": { "type": "string" },"user": { "type": "object","properties": {"id": { "type": "string" },"gender": { "type": "string" },"age": { "type": "long" },"name": { "type": "object","properties": {"full": { "type": "string" },"first": { "type": "string" },"last": { "type": "string" }}}}}}}} }

type 映射(tweet)只是一種特殊的 對象 映射,我們稱之為 根對象。

Lucene 不理解內(nèi)部對象。 Lucene 文檔是由一組鍵值對列表組成的。為了能讓 Elasticsearch 有效地索引內(nèi)部類,它把我們的文檔轉(zhuǎn)化成這樣:

{"tweet": [elasticsearch, flexible, very],"user.id": [@johnsmith],"user.gender": [male],"user.age": [26],"user.name.full": [john, smith],"user.name.first": [john],"user.name.last": [smith] }

內(nèi)部域 可以通過名稱引用(例如, first )。為了區(qū)分同名的兩個域,我們可以使用全 路徑 (例如, user.name.first ) 或 type 名加路徑( tweet.user.name.first )。

  • 內(nèi)部對象數(shù)組

假設我們有個 followers 數(shù)組:

{"followers": [{ "age": 35, "name": "Mary White"},{ "age": 26, "name": "Alex Jones"},{ "age": 19, "name": "Lisa Smith"}] }

這個文檔會像我們之前描述的那樣被扁平化處理,結(jié)果如下所示:

{"followers.age": [19, 26, 35],"followers.name": [alex, jones, lisa, smith, mary, white] }

{age: 35} 和 {name: Mary White} 之間的相關(guān)性已經(jīng)丟失了,因為每個多值域只是一包無序的值,而不是有序數(shù)組。這足以讓我們問,“有一個26歲的追隨者?”

但是我們不能得到一個準確的答案:“是否有一個26歲 名字叫 Alex Jones 的追隨者?”

相關(guān)內(nèi)部對象被稱為 nested 嵌套對象,可以回答上面的查詢,這里暫不做研究。

2. 索引

2.1 什么是索引

索引是es中存儲數(shù)據(jù)的一種邏輯,大部分人對mysql會更熟悉一些,可以對比下

(1)關(guān)系型數(shù)據(jù)庫中的數(shù)據(jù)庫(DataBase),等價于ES中的索引(Index)

(2)一個數(shù)據(jù)庫下面有N張表(Table),等價于1個索引Index下面有N多類型(Type)

(3)一個數(shù)據(jù)庫表(Table)下的數(shù)據(jù)由多行(ROW)多列(column,屬性)組成,等價于1個Type由多個文檔(Document)和多Field組成。

(4)在一個關(guān)系型數(shù)據(jù)庫里面,schema定義了表、每個表的字段,還有表和字段之間的關(guān)系。 與之對應的,在ES中:Mapping定義索引下的Type的字段處理規(guī)則,即索引如何建立、索引類型、是否保存原始索引JSON文檔、是否壓縮原始JSON文檔、是否需要分詞處理、如何進行分詞處理等。

2.2 創(chuàng)建一個默認配置的索引

curl -XPOST 'http://localhost:9200/posts'

以上索引采用的是默認配置,新的字段通過『動態(tài)映射』的方式被添加到類型映射。當然我們可以做更多的控制,手動創(chuàng)建索引,在請求體里傳入設置或類型映射:

PUT /my_index {"settings": { ... any settings ... },"mappings": {"type_one": { ... any mappings ... },"type_two": { ... any mappings ... },...} }

上面分為兩部分,第一部分是settings,第二部分是mappings

2.3 索引的設置(settings部分)

可以通過修改配置來自定義索引行為,但是除非你理解這些配置的作用并且知道為什么要去修改,否則不要隨意修改,Elasticsearch 已經(jīng)提供了優(yōu)化好的默認配置。

配置:

? 1、number_of_shards

每個索引的主分片數(shù),默認值是 5 。這個配置在索引創(chuàng)建后不能修改。

? 2、number_of_replicas

每個主分片的副本數(shù),默認值是 1 。對于活動的索引庫,這個配置可以隨時修改。

例如,我們可以創(chuàng)建只有 一個主分片,沒有副本的小索引:

PUT /my_temp_index {"settings": {"number_of_shards" : 1,"number_of_replicas" : 0} }

? 3、配置分析器

第三個重要的索引設置是 analysis 部分, 用來配置已存在的分析器或針對你的索引創(chuàng)建新的自定義分析器,后面編寫映射的

前面我們已經(jīng)介紹了一些內(nèi)置的分析器,用于將全文字符串轉(zhuǎn)換為適合搜索的倒排索引。

standard 分析器是用于全文字段的默認分析器, 對于大部分西方語系來說是一個不錯的選擇。 它包括了以下幾點:

  • standard 分詞器,通過單詞邊界分割輸入的文本。
  • standard 語匯單元過濾器,目的是整理分詞器觸發(fā)的語匯單元(但是目前什么都沒做)。
  • lowercase 語匯單元過濾器,轉(zhuǎn)換所有的語匯單元為小寫。
  • stop 語匯單元過濾器,刪除停用詞--對搜索相關(guān)性影響不大的常用詞,如 a , the , and , is

默認情況下,停用詞過濾器是被禁用的。如需啟用它,你可以通過創(chuàng)建一個基于 standard 分析器的自定義分析器并設置 stopwords 參數(shù)。 可以給分析器提供一個停用詞列表,或者告知使用一個基于特定語言的預定義停用詞列表。

在下面的例子中,我們創(chuàng)建了一個新的分析器,叫做 es_std , 并使用預定義的 西班牙語停用詞列表:

PUT /spanish_docs {"settings": {"analysis": {"analyzer": {"es_std": {"type": "standard","stopwords": "_spanish_"}}}} }

es_std 分析器不是全局的--它僅僅存在于我們定義的 spanish_docs 索引中。 為了使用 analyze API來對它進行測試,我們必須使用特定的索引名:

GET /spanish_docs/_analyze?analyzer=es_std El veloz zorro marrón

簡化的結(jié)果顯示西班牙語停用詞 El 已被正確的移除:

{"tokens" : [{ "token" : "veloz", "position" : 2 },{ "token" : "zorro", "position" : 3 },{ "token" : "marrón", "position" : 4 }] }

? ?自定義分析器

和我們之前配置 es_std 分析器一樣,我們可以在 analysis 下的相應位置設置 字符過濾器 、 分詞器 和 詞單元過濾器:

PUT /my_index {"settings": {"analysis": {"char_filter": { ... custom character filters ... },"tokenizer": { ... custom tokenizers ... },"filter": { ... custom token filters ... },"analyzer": { ... custom analyzers ... }}} }

作為示范,讓我們一起來創(chuàng)建一個自定義分析器吧,字符過濾器 實現(xiàn)1、2、 分詞器 實現(xiàn)3, 詞單元過濾器實現(xiàn)4、5:

1、使用 html清除 字符過濾器移除HTML部分。(html_strip)

2、使用一個自定義的 映射 字符過濾器把 & 替換為 " and " :(_to_and)

"char_filter": {"&_to_and": {"type": "mapping","mappings": [ "&=> and "]} }

3、使用 標準 分詞器分詞。(standard)

4、小寫詞條,使用 小寫 詞過濾器處理。(lowercase)

5、使用自定義 停止 詞過濾器移除自定義的停止詞列表中包含的詞:(my_stopwords)

"filter": {"my_stopwords": {"type": "stop","stopwords": [ "the", "a" ]} }

一個完整的示例

PUT /my_index {"settings": {"analysis": {"char_filter": {"&_to_and": {"type": "mapping","mappings": [ "&=> and "]}},"filter": {"my_stopwords": {"type": "stop","stopwords": [ "the", "a" ]}},"analyzer": {"my_analyzer": {"type": "custom","char_filter": [ "html_strip", "&_to_and" ],"tokenizer": "standard","filter": [ "lowercase", "my_stopwords" ]}} }}}

索引被創(chuàng)建以后,使用 analyze API 來 測試這個新的分析器:

GET /my_index/_analyze?analyzer=my_analyzer The quick & brown fox

下面的縮略結(jié)果展示出我們的分析器正在正確地運行:

{"tokens" : [{ "token" : "quick", "position" : 2 },{ "token" : "and", "position" : 3 },{ "token" : "brown", "position" : 4 },{ "token" : "fox", "position" : 5 }] }

這個分析器現(xiàn)在是沒有多大用處的,除非我們告訴 Elasticsearch在哪里用上它。我們可以像下面這樣把這個分析器應用在一個 string 字段上:

PUT /my_index/_mapping/my_type {"properties": {"title": {"type": "string","analyzer": "my_analyzer"}} }

2.4 索引的映射配置(mappings部分)

2.4.1 映射寫法

比如索引gb下有tweet和user類型,那么映射應該如何定義呢,類似于下面

{"gb": {"mappings": {"tweet": {"properties": {"date": {"type": "date","format": "strict_date_optional_time||epoch_millis"},"name": {"type": "string"},"tweet": {"type": "string"},"user_id": {"type": "long"}}},"user":{...}}} }

上面json數(shù)據(jù)層次如下

索引gb-> mappings-> 類型tweet-> properites-> 字段date字段name......類型user-> properites-> 字段aa字段bb......

接下來梳理下映射的配置項

2.4.2 類型

關(guān)于配置中類型怎么處理很簡單,如果有多個類型,那么就并列的嵌套在mappings對象下。

但是,這里我們有必要進一步了解下類型

類型實際上是個邏輯區(qū)分,每個文檔的類型名被存儲在一個叫 _type 的元數(shù)據(jù)字段上。 當我們要檢索某個類型的文檔時, Elasticsearch 通過在 _type 字段上使用過濾器限制只返回這個類型的文檔。

如果有兩個不同的類型,每個類型都有同名的字段,但映射不同(例如:一個是字符串一個是數(shù)字),那么當配置這樣的映射時候會出現(xiàn)異常。因為在 Elasticsearch 中的所有類型最終都共享相同的映射,

以 data 索引中兩種類型的映射為例(只是演示,不真實有效):

{"data": {"mappings": {"people": {"properties": {"name": {"type": "string",},"address": {"type": "string"}}},"transactions": {"properties": {"timestamp": {"type": "date","format": "strict_date_optional_time"},"message": {"type": "string"}}}}} }

每個類型定義兩個字段 (分別是 "name"/"address" 和 "timestamp"/"message" )。它們看起來是相互獨立的,但在后臺 Lucene 將創(chuàng)建一個映射,如:

{"data": {"mappings": {"_type": {"type": "string","index": "not_analyzed"},"name": {"type": "string"}"address": {"type": "string"}"timestamp": {"type": "long"}"message": {"type": "string"}}} }

結(jié)論:

  • 多個類型可以在相同的索引中存在,只要它們的字段不沖突,類型可以很好的區(qū)分同一個集合中的不同細分,

  • 類型不適合 完全不同類型的數(shù)據(jù) 。如果兩個類型的字段集是互不相同的,這就意味著索引中將有一半的數(shù)據(jù)是空的(字段將是 稀疏的 ),最終將導致性能問題。在這種情況下,最好是使用兩個單獨的索引。

2.4.3 根對象

映射的最高一層被稱為 根對象 ,它可能包含下面幾項:

  • 一個 properties 節(jié)點,列出了文檔中可能包含的每個字段的映射
  • 各種元數(shù)據(jù)字段,它們都以一個下劃線開頭,例如 _type 、 _id 和 _source
  • 設置項,控制如何動態(tài)處理新的字段,例如 analyzer 、 dynamic_date_formats 和 dynamic_templates
  • 其他設置,可以同時應用在根對象和其他 object 類型的字段上,例如 enabled 、 dynamic 和 include_in_all

在一個映射配置中的部分選項的位置示例:

{"gb": {"mappings": {"people": {"_source": {"enabled": false},"_all": {"enabled": false},"properties": {"name": {"type": "string","index": "analyzed","analyzer": "english"},"address": {"type": "string"}}},}} }

? 1、屬性

  • type屬性

字段的數(shù)據(jù)類型,例如 string 或 date

對于不是 string 的域,你一般只需要設置 type :

{"number_of_clicks": {"type": "integer"} }

默認, string 類型域會被認為包含全文。就是說,它們的值在索引前,會通過 一個分析器,針對于這個域的查詢在搜索前也會經(jīng)過一個分析器。

  • index屬性

字段是否應當被當成全文來搜索( analyzed ),或被當成一個準確的值( not_analyzed ),還是完全不可被搜索( no )

index 屬性控制怎樣索引字符串。它可以是下面三個值:

analyzed 首先分析字符串,然后索引它。換句話說,以全文索引這個域。

not_analyzed 索引這個域,所以它能夠被搜索,但索引的是精確值。不會對它進行分析。

no 不索引這個域。這個域不會被搜索到。

string 域 index 屬性默認是 analyzed 。如果我們想映射這個字段為一個精確值,我們需要設置它為 not_analyzed :

{"tag": {"type": "string","index": "not_analyzed"} }

其他簡單類型(例如 long , double , date 等)也接受 index 參數(shù),但有意義的值只有 no 和 not_analyzed , 因為它們永遠不會被分析。

  • analyzer屬性

對于 analyzed 字符串域,用 analyzer 屬性指定在搜索和索引時使用的分析器。上面我們用了很多篇幅介紹了分析器內(nèi)容,在這里就可以使用這些分析器了。默認, Elasticsearch 使用 standard 分析器, 但你可以指定一個內(nèi)置的分析器替代它,例如 whitespace 、 simple 和 english:

{"tweet": {"type": "string","analyzer": "english"} }
  • multi_field類型

有時候需要將同一個值,存入到不同的字段,例如一個字段用于搜索,另一個字段用于統(tǒng)計。這時我們就可以使用multi_field來實現(xiàn)

{"gb": {"mappings": {"user": {"properties": {"name": {"type": "multi_field","fields": {"name": {"type": "string","index": "analyzed"},"facet": {"type": "string","index": "not_analyzed"}}},}},}} }

上述定義會創(chuàng)建兩個字段,一個通過name來引用,另一個通過name.facet引用。當然創(chuàng)建索引的時候沒有必要專門指定兩個不同字段,一個name字段就可以了,es會自動完成剩余的工作。

? 2、元數(shù)據(jù):_source字段

默認地,Elasticsearch 在 _source 字段存儲代表文檔體的JSON字符串, _source 字段在被寫入磁盤之前先會被壓縮。

擁有該字段意味著下面這些:

  • 搜索結(jié)果包括了整個可用的文檔——不需要額外的從另一個的數(shù)據(jù)倉庫來取文檔。
  • 如果沒有 _source 字段,部分 update 請求不會生效。
  • 當你的映射改變時,你需要重新索引你的數(shù)據(jù),有了_source字段你可以直接從Elasticsearch這樣做,而不必從另一個(通常是速度更慢的)數(shù)據(jù)倉庫取回你的所有文檔。
  • 當你不需要看到整個文檔時,單個字段可以從 _source 字段提取和通過 get 或者 search 請求返回。
  • 調(diào)試查詢語句更加簡單,因為你可以直接看到每個文檔包括什么,而不是從一列id猜測它們的內(nèi)容。

然而,存儲 _source 字段的確要使用磁盤空間。如果上面的原因?qū)δ銇碚f沒有一個是重要的,你可以用下面的映射禁用 _source 字段:

PUT /my_index {"mappings": {"my_type": {"_source": {"enabled": false},"properties": {......}}} }

在一個搜索請求里,你可以通過在請求體中指定 _source 參數(shù),來達到只獲取特定的字段的效果:

GET /_search {"query": { "match_all": {}},"_source": [ "title", "created" ] }

這些字段的值會從 _source 字段被提取和返回,而不是返回整個 _source 。

? 3、 元數(shù)據(jù):_all字段

_all 字段:一個把其它字段值 當作一個大字符串來索引的特殊字段。 query_string 查詢子句(搜索 ?q=john )在沒有指定字段時默認使用 _all 字段。

_all 字段在新應用的探索階段,當你還不清楚文檔的最終結(jié)構(gòu)時是比較有用的。你可以使用這個字段來做任何查詢,并且有很大可能找到需要的文檔:

GET /_search {"match": {"_all": "john smith marketing"} }

隨著應用的發(fā)展,搜索需求變得更加明確,你會發(fā)現(xiàn)自己越來越少使用 _all 字段。 _all 字段是搜索的應急之策。通過查詢指定字段,你的查詢更加靈活、強大,你也可以對相關(guān)性最高的搜索結(jié)果進行更細粒度的控制。

如果你不再需要 _all 字段,你可以通過下面的映射來禁用:

PUT /my_index/_mapping/my_type {"my_type": {"_all": { "enabled": false },"properties": {......}} }

_all字段會增加索引的大小,因為在不需要使用的時候最好禁用。

通過 include_in_all 設置來逐個控制字段是否要包含在 _all 字段中,默認值是 true。在一個對象(或根對象)上設置 include_in_all 可以修改這個對象中的所有字段的默認行為。

你可能想要保留 _all 字段作為一個只包含某些特定字段的全文字段,例如只包含 title,overview,summary 和 tags。 相對于完全禁用 _all 字段,你可以為所有字段默認禁用 include_in_all 選項,僅在你選擇的字段上啟用:

PUT /my_index/my_type/_mapping {"my_type": {"include_in_all": false,"properties": {"title": {"type": "string","include_in_all": true},...}} }

記住,_all 字段僅僅是一個 經(jīng)過分詞的 string 字段。它使用默認分詞器來分析它的值,不管這個值原本所在字段指定的分詞器。就像所有 string 字段,你可以配置 _all 字段使用的分詞器:

PUT /my_index/my_type/_mapping {"my_type": {"_all": { "analyzer": "whitespace" }} }

2.4.4 動態(tài)映射

我們開頭就說過es會自動匹配數(shù)據(jù)結(jié)構(gòu),這種機制其實就是動態(tài)映射,當 Elasticsearch 遇到文檔中以前 未遇到的字段,它用 dynamic mapping 來確定字段的數(shù)據(jù)類型并自動把新的字段添加到類型映射。

上面我們又考慮到,想要自己定義數(shù)據(jù)結(jié)構(gòu),所有要自己實現(xiàn)配置分析器,定義映射關(guān)系,但是我們想要新加一個字段,這時候還是會用到動態(tài)映射。

有時這是想要的行為有時又不希望這樣。通常沒有人知道以后會有什么新字段加到文檔,但是又希望這些字段被自動的索引。也許你只想忽略它們。如果Elasticsearch是作為重要的數(shù)據(jù)存儲,可能就會期望遇到新字段就會拋出異常,這樣能及時發(fā)現(xiàn)問題。

幸運的是可以用 dynamic 配置來控制這種行為 ,可接受的選項如下:

  • true 動態(tài)添加新的字段--缺省
  • false 忽略新的字段
  • strict 如果遇到新字段拋出異常

配置參數(shù) dynamic 可以用在根 object 或任何 object 類型的字段上。你可以將 dynamic 的默認值設置為 strict , 而只在指定的內(nèi)部對象中開啟它, 例如:

PUT /my_index {"mappings": {"my_type": {"dynamic": "strict", "properties": {"title": { "type": "string"},"stash": {"type": "object","dynamic": true }}}} }

把 dynamic 設置為 false 一點兒也不會改變 _source 的字段內(nèi)容。 _source 仍然包含被索引的整個JSON文檔。只是新的字段不會被加到映射中也不可搜索。

2.4.5 自定義動態(tài)映射

有時候你想增加新的字段,也想用動態(tài)映射,但是動態(tài)映射又不是很只能,幸運的是,es允許我們自己定義動態(tài)映射的規(guī)則。

通過動態(tài)模板,你可以完全控制 新檢測生成字段的映射。你甚至可以通過字段名稱或數(shù)據(jù)類型來應用不同的映射。

每個模板都有一個名稱, 你可以用來描述這個模板的用途, 一個 mapping 來指定映射應該怎樣使用,以及至少一個參數(shù) (如 match) 來定義這個模板適用于哪個字段。

模板按照順序來檢測;第一個匹配的模板會被啟用。例如,我們給 string 類型字段定義兩個模板:

  • es :以 _es 結(jié)尾的字段名需要使用 spanish 分詞器。
  • en :所有其他字段使用 english 分詞器。

我們將 es 模板放在第一位,因為它比匹配所有字符串字段的 en 模板更特殊:

PUT /my_index {"mappings": {"my_type": {"dynamic_templates": [{ "es": {"match": "*_es", "match_mapping_type": "string","mapping": {"type": "string","analyzer": "spanish"}}},{ "en": {"match": "*", "match_mapping_type": "string","mapping": {"type": "string","analyzer": "english"}}}] }}}
  • match_mapping_type 允許你應用模板到特定類型的字段上,就像有標準動態(tài)映射規(guī)則檢測的一樣, (例如 string 或 long)。
  • match 參數(shù)只匹配字段名稱
  • path_match 參數(shù)匹配字段在對象上的完整路徑,所以 address.*.name 將匹配這樣的字段:
{"address": {"city": {"name": "New York"}} }
  • unmatch 和 path_unmatch將被用于未被匹配的字段。

2.4.6 缺省映射

通常,一個索引中的所有類型共享相同的字段和設置。 default 映射更加方便地指定通用設置,而不是每次創(chuàng)建新類型時都要重復設置。 default 映射是新類型的模板。在設置 default 映射之后創(chuàng)建的所有類型都將應用這些缺省的設置,除非類型在自己的映射中明確覆蓋這些設置。

例如,我們可以使用 default 映射為所有的類型禁用 _all 字段, 而只在 blog 類型啟用:

PUT /my_index {"mappings": {"_default_": {"_all": { "enabled": false }},"blog": {"_all": { "enabled": true }}} }

不難發(fā)現(xiàn),default 映射也可以指定映射規(guī)則,所以_default_ 映射也是一個指定索引 dynamic templates 的好方法。

2.5 索引的管理

2.5.1 創(chuàng)建索引

創(chuàng)建一個使用默認配置的索引

curl -XPOST 'http://localhost:9200/posts'

創(chuàng)建一個手動定義規(guī)則的索引

PUT /my_index {"settings": { ... any settings ... },"mappings": {"type_one": { ... any mappings ... },"type_two": { ... any mappings ... },...} }

2.5.2 查看索引

GET /gb/_mapping/tweet

通過 /_mapping ,我們可以查看 Elasticsearch 在一個或多個索引中的一個或多個類型的映射

{"gb": {"mappings": {"tweet": {"properties": {"date": {"type": "date","format": "strict_date_optional_time||epoch_millis"},"name": {"type": "string"},"tweet": {"type": "string"},"user_id": {"type": "long"}}}}} }

2.5.3 刪除索引

# 刪除一個索引 DELETE /my_index# 刪除 多個 索引: DELETE /index_one,index_two DELETE /index_*# 刪除 全部 索引: DELETE /_all DELETE /*

2.5.4 重構(gòu)索引

  • 如果索引中還沒有任何數(shù)據(jù)

最簡單的方法就是刪除索引,然后重新按照自己的需求建立。

  • 如果已經(jīng)有數(shù)據(jù)

對現(xiàn)有數(shù)據(jù)的這類改變最簡單的辦法就是重新索引:用新的設置創(chuàng)建新的索引并把文檔從舊的索引復制到新的索引。

字段 _source 的一個優(yōu)點是在Elasticsearch中已經(jīng)有整個文檔。你不必從源數(shù)據(jù)中重建索引,而且那樣通常比較慢。

為了有效的重新索引所有在舊的索引中的文檔,用 scroll 從舊的索引檢索批量文檔 , 然后用 bulk API (批量寫入)把文檔推送到新的索引中。

轉(zhuǎn)載于:https://www.cnblogs.com/redirect/p/8436072.html

與50位技術(shù)專家面對面20年技術(shù)見證,附贈技術(shù)全景圖

總結(jié)

以上是生活随笔為你收集整理的elasticsearch索引和映射的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。