ElasticStack系列,第二章

ElasticStack系列,第二章

一、ElasticSearch核心內容詳解

1、文檔

{
    _index: "haoke"
    _type: "user"
    _id: "FD_2gm4BoifuYiH46rUl"
    _version: 1
    found: true
    _source: {
        id: 1002
        name: "李四"
        age: 21
        sex: "男"
    }-
}

元數據:

1、_index	文檔存儲的地方:
類似於關係型數據庫裏的“數據庫”,它是我們存儲和索引關聯數據的地方。


2、_type	文檔代表的對象的類
在關係型數據庫中,我們經常將相同類的對象存儲在一個表裏,因爲它們有着相同的結構。
同理,在Elasticsearch中,我們使用相同類型(type)的文檔表示相同的“事物”,
因爲他們的數據結構也是相同的。


3、_id		文檔的唯一標識
id僅僅是一個字符串,它與 _index 和 _type 組合時,就可以在Elasticsearch中
唯一標識一個文檔。當創建一個文檔,你可以自定義 _id ,也可以讓Elasticsearch
幫你自動生成(32位長度)。

2、查詢響應

①、平常查詢的時候,相應沒有格式化,是這樣的:

GET  http://IP:9200/haoke/user/FT_Hh24BoifuYiH4yLVZ 
{"_index":"haoke","_type":"user","_id":"FT_Hh24BoifuYiH4yLVZ","_version":1,"found":true,"_source":{ "id":1002,"name":"李四","age":21, "sex":"女"}}

想要結果格式化在之後加一個?pretty即可:

GET http://IP:9200/haoke/user/FT_Hh24BoifuYiH4yLVZ?pretty 
{
  "_index" : "haoke",
  "_type" : "user",
  "_id" : "FT_Hh24BoifuYiH4yLVZ",
  "_version" : 1,
  "found" : true,
  "_source" : {
    "id" : 1002,
    "name" : "李四",
    "age" : 21,
    "sex" : "女"
  }
}

②、查詢只返回數據,不要元數據

請求:

GET http://IP:9200/haoke/user/FT_Hh24BoifuYiH4yLVZ/_source	##斜線

結果:

{ 
    "id":1002, 
    "name":"李四", 
    "age":21, 
    "sex":"女"
}

③、查詢只返回指定的字段

請求:

GET http://IP:9200/haoke/user/FT_Hh24BoifuYiH4yLVZ?_source=id,name ##問號

結果:

{
    "_index":"haoke",
    "_type":"user",
    "_id":"FT_Hh24BoifuYiH4yLVZ",
    "_version":1,
    "found":true,
    "_source":{
        "name":"李四",
        "id":1002
    }
}

④、既不返回元數據,也只返回指定字段

請求:

GET http://IP:9200/haoke/user/FT_Hh24BoifuYiH4yLVZ/_source?_source=id,name ##斜線+問號

結果:

{
    "name":"李四",
    "id":1002
}

⑤、判斷文檔是否存在

請求:

HEAD http://IP:9200/haoke/user/FT_Hh24BoifuYiH4yLVZ

結果:

存在:
	Status: 200 OK    Time: 53ms
不存在:
	Status: 404 NOT Found    Time: 210ms

3、批量操作

①、_mget 查詢

A、同一個_index 同一個 _type下

請求:

POST  http://IP:9200/haoke/user/_mget

請求body:
{ 
	"ids" : [ "FT_Hh24BoifuYiH4yLVZ", "Fj_Ih24BoifuYiH4mrUZ" ]
}

結果:

{
    "docs": [
        {
            "_index": "haoke",
            "_type": "user",
            "_id": "FT_Hh24BoifuYiH4yLVZ",
            "_version": 1,
            "found": true,
            "_source": {
                "id": 1002,
                "name": "李四",
                "age": 21,
                "sex": "女"
            }
        },
        {
            "_index": "haoke",
            "_type": "user",
            "_id": "Fj_Ih24BoifuYiH4mrUZ",
            "_version": 1,
            "found": true,
            "_source": {
                "id": 1001,
                "name": "張三",
                "age": 20,
                "sex": "男"
            }
        }
    ]
}

B、同一個_index 不同 _type下

請求:

POST http://IP:9200/haoke/_mget

請求body:
{
	"docs":[
		{
			"_type":"user",##類型1
			"_id":"FT_Hh24BoifuYiH4yLVZ"
		},
		{
			"_type":"user",##類型2
			"_id":"Fj_Ih24BoifuYiH4mrUZ"
		},
	]
}

結果:

{
    "docs": [
        {
            "_index": "haoke",
            "_type": "user",
            "_id": "FT_Hh24BoifuYiH4yLVZ",
            "_version": 1,
            "found": true,
            "_source": {
                "id": 1002,
                "name": "李四",
                "age": 21,
                "sex": "女"
            }
        },
        {
            "_index": "haoke",
            "_type": "user",
            "_id": "Fj_Ih24BoifuYiH4mrUZ",
            "_version": 1,
            "found": true,
            "_source": {
                "id": 1001,
                "name": "張三",
                "age": 20,
                "sex": "男"
            }
        }
    ]
}

C、不同_index 和 不同 _type下

請求:

POST http://IP:9200/_mget

請求body:
{
	"docs":[
		{
			"_index":"haoke",##索引1
			"_type":"user",##類型1
			"_id":"FT_Hh24BoifuYiH4yLVZ"
		},
		{
			"_index":"haoke",##索引2
			"_type":"user",##類型2
			"_id":"Fj_Ih24BoifuYiH4mrUZ"
		}
	]
}

結果:

{
    "docs": [
        {
            "_index": "haoke",
            "_type": "user",
            "_id": "FT_Hh24BoifuYiH4yLVZ",
            "_version": 1,
            "found": true,
            "_source": {
                "id": 1002,
                "name": "李四",
                "age": 21,
                "sex": "女"
            }
        },
        {
            "_index": "haoke",
            "_type": "user",
            "_id": "Fj_Ih24BoifuYiH4mrUZ",
            "_version": 1,
            "found": true,
            "_source": {
                "id": 1001,
                "name": "張三",
                "age": 20,
                "sex": "男"
            }
        }
    ]
}

D、可以具體的字段

請求:

POST http://IP:9200/_mget

請求body:
{
	"docs":[
		{
			"_index":"haoke",
			"_type":"user",
			"_id":"FT_Hh24BoifuYiH4yLVZ",
			"_source":"name"
		},
		{
			"_index":"haoke",
			"_type":"user",
			"_id":"Fj_Ih24BoifuYiH4mrUZ",
			"_source":["name","age"]
		}
	]
}

結果:

{
    "docs": [
        {
            "_index": "haoke",
            "_type": "user",
            "_id": "FT_Hh24BoifuYiH4yLVZ",
            "_version": 1,
            "found": true,
            "_source": {
                "name": "李四"
            }
        },
        {
            "_index": "haoke",
            "_type": "user",
            "_id": "Fj_Ih24BoifuYiH4mrUZ",
            "_version": 1,
            "found": true,
            "_source": {
                "name": "張三",
                "age": 20
            }
        }
    ]
}

②、_bulk 增刪改

格式:

{ action: { metadata }}
{ request body		  }

{ action: { metadata }}
{ request body        }

A、批量添加

請求:

http://IP:9200/_bulk

請求body:
{"create":{"_index":"haoke","_type":"user","_id":"aaa"}}
{"id":1001,"name":"name1","age":20,"sex":"男"}
{"create":{"_index":"haoke","_type":"user","_id":"bbb"}}
{"id":1002,"name":"name2","age":21,"sex":"女"}
{"create":{"_index":"haoke","_type":"user","_id":"ccc"}}
{"id":1003,"name":"name3","age":22,"sex":"女"}

或者:

{"index":{"_index":"haoke","_type":"user","_id":"aaa"}}
{"id":1001,"name":"name1","age":20,"sex":"男"}
{"index":{"_index":"haoke","_type":"user","_id":"bbb"}}
{"id":1002,"name":"name2","age":21,"sex":"女"}
{"index":{"_index":"haoke","_type":"user","_id":"ccc"}}
{"id":1003,"name":"name3","age":22,"sex":"女"}

結果:

在這裏插入圖片描述

B、批量刪除

請求:

POST http://IP:9200/_bulk

請求body:
{"delete":{"_index":"haoke","_type":"user","_id":"aaa"}}
{"delete":{"_index":"haoke","_type":"user","_id":"bbb"}}
{"delete":{"_index":"haoke","_type":"user","_id":"ccc"}}

結果:

在這裏插入圖片描述

C、批量修改–全量覆蓋修改

請求:

http://IP:9200/_bulk

請求body:

{"index":{"_index":"haoke","_type":"user","_id":"aaa"}}
{"id":1001,"name":"name111","age":20,"sex":"男"}
{"index":{"_index":"haoke","_type":"user","_id":"bbb"}}
{"id":1002,"name":"name222","age":21,"sex":"女"}
{"index":{"_index":"haoke","_type":"user","_id":"ccc"}}
{"id":1003,"name":"name333","age":22,"sex":"女"}

結果:

在這裏插入圖片描述

D、批量修改-局部修改

請求:

http://IP:9200/_bulk

請求body:
{"update":{"_index":"haoke","_type":"user","_id":"aaa"}}
{"doc":{"name":"name111a"}}
{"update":{"_index":"haoke","_type":"user","_id":"bbb"}}
{"doc":{"name":"name222b"}}
{"update":{"_index":"haoke","_type":"user","_id":"ccc"}}
{"doc":{"name":"name333c"}}

結果:

在這裏插入圖片描述

總結:

一次請求多少性能最高?

整個批量請求需要被加載到接受我們請求節點的內存裏,所以請求越大,給其它請求可用的內存就越小。
有一個最佳的bulk請求大小。超過這個大小,性能不再提升而且可能降低。


最佳大小,當然並不是一個固定的數字。它完全取決於你的硬件、你文檔的大小和複雜度以及索引和搜索的負載。


幸運的是,這個最佳點(sweetspot)還是容易找到的:試着批量索引標準的文檔,隨着大小的增長,當性能開始降低,
說明你每個批次的大小太大了。開始的數量可以在1000~5000個文檔之間,如果你的文檔非常大,可以使用較小的批次。


通常着眼於你請求批次的物理大小是非常有用的。一千個1kB的文檔和一千個1MB的文檔大不相同。
一個好的批次最好保持在5-15MB大小間。

4、分頁

和SQL使用 LIMIT 關鍵字返回只有一頁的結果一樣,Elasticsearch接受 from 和 size 參數:

size: 結果數,默認10
from: 跳過開始的結果數,默認0

如果你想每頁顯示5個結果,頁碼從1到3,那請求如下:

GET /_search?size=5
GET /_search?size=5&from=5
GET /_search?size=5&from=10

注意:

應該當心分頁太深或者一次請求太多的結果。結果在返回前會被排序。但是記住一個搜索請求常常涉及多個分片。
每個分片生成自己排好序的結果,它們接着需要集中起來排序以確保整體排序正確。

爲了理解爲什麼深度分頁是有問題的,讓我們假設在一個有5個主分片的索引中搜索。當我們請求結果的第一頁
(結果1到10)時,每個分片產生自己最頂端10個結果然後返回它們給請求節點(requesting node),
它再排序這所有的50個結果以選出頂端的10個結果。現在假設我們請求第1000頁——結果10001到10010。
工作方式都相同,不同的是每個分片都必須產生頂端的10010個結果。然後請求節點排序這50050個結果並丟
棄50040個!你可以看到在分佈式系統中,排序結果的花費隨着分頁的深入而成倍增長。這也是爲什麼網絡搜
索引擎中任何語句不能返回多於1000個結果的原因。

5、映射

前面我們創建的索引以及插入數據,都是由Elasticsearch進行自動判斷類型,有些時候我們是需要進行明確字段類型的,否則,自動判斷的類型和實際需求是不相符的。自動判斷的規則如下:

JSON type Field type
Boolean: true or false “boolean”
Whole number: 123 “long”
Floating point: 123.45 “double”
String, valid date: “2014-09-15” “date”
String: “foo bar” “string”

Elasticsearch中支持的類型如下:

類型 表示的數據類型
String string , text , keyword
Whole number byte , short , integer , long
Floating point float , double
Boolean boolean
Date date
  • string類型在ElasticSearch 舊版本中使用較多,從ElasticSearch 5.x開始不再支持string,由text和keyword類型替代。
  • text 類型,當一個字段是要被全文搜索的,比如Email內容、產品描述,應該使用text類型。設置text類型以後,字段內容會被分析,在生成倒排索引以前,字符串會被分析器分成一個一個詞項。text類型的字段不用於排序,很少用於聚合。【要被分詞】
  • keyword類型適用於索引結構化的字段,比如email地址、主機名、狀態碼和標籤。如果字段需要進行過濾(比如查找已發佈博客中status屬性爲published的文章)、排序、聚合。keyword類型的字段只能通過精確值搜索到。【不參與分詞】

使用:

##插入索引,並創建映射
PUT /lee
{
    "settings":{
        "index":{
            "number_of_shards":"2",
            "number_of_replicas":"0"
        }
    },
    "mappings":{
        "person":{
            "properties":{
                "name":{
                    "type":"text"
                },
                "age":{
                    "type":"integer"
                },
                "mail":{
                    "type":"keyword"
                },
                "hobby":{
                    "type":"text"
                }
            }
        }
    }
}

##查看映射
GET /lee/_mapping

插入一些數據,後面要用到:

GET /lee/_mapping

{"index":{"_index":"itcast","_type":"person"}}
{"name":"張三","age": 20,"mail": "[email protected]","hobby":"羽毛球、乒乓球、足球"}
{"index":{"_index":"itcast","_type":"person"}}
{"name":"李四","age": 21,"mail": "[email protected]","hobby":"羽毛球、乒乓球、足球、籃球"}
{"index":{"_index":"itcast","_type":"person"}}
{"name":"王五","age": 22,"mail": "[email protected]","hobby":"羽毛球、籃球、游泳、聽音樂"}
{"index":{"_index":"itcast","_type":"person"}}
{"name":"趙六","age": 23,"mail": "[email protected]","hobby":"跑步、游泳"}
{"index":{"_index":"itcast","_type":"person"}}
{"name":"孫七","age": 24,"mail": "[email protected]","hobby":"聽音樂、看電影"}

在這裏插入圖片描述

6、結構化查詢

①、term

term 主要用於精確匹配哪些值,比如**“數字”,“日期",“布爾值” 或 “不能分詞的字符串”**(未經分析的文本數據類型):

{ "term": { "age": 26} } 
{ "term": { "date":"2014-09-01"} } 
{ "term": { "public": true} } 
{ "term": { "tag": "full_text"} }

示例:(查詢年齡爲20的person)

POST /lee/person/_search

{
    "query":{
        "term":{
            "age":20
        }
    }
}

注意:

不能匹配text

②、terms

terms 跟 term 有點類似,但 terms 允許指定多個匹配條件。 如果某個字段指定了多個值,那麼文檔需要一起去做匹配:( 類似SQL中的 in )

示例:(查詢年齡爲20,21,22的person)

POST /lee/person/_search

{
    "query":{
        "terms":{
            "age":[ 20,21,22]
        }
    }
}

③、range

range 過濾允許我們按照指定範圍查找一批數據:

符號 意義
gt 大於
gte 大於等於
lt 小於
lte 小於等於

示例:(查詢年齡大於等於20小於等於22的人)

POST /lee/person/_search

{
    "query":{
        "range":{
            "age":{
                "gte":20,
                "lte":22
            }
        }
    }
}

④、exists

exists 查詢可以用於查找文檔中是否包含指定字段或沒有某個字段,類似於SQL語句中的 IS_NULL 條件**(字段是否存在)**

語法:

{
	"query":{
		"exists":{
			"field":"字段"
		}
	}
}

示例:

POST http://IP:9200/lee/person/_search

{
	"query":{
		"exists":{
			"field":"gender"
		}
	}
}

⑤、match

match 查詢是一個標準查詢,不管你需要全文本查詢還是精確查詢基本上都要用到它。

A、如果你使用 match 查詢一個**“全文本字段”,它會在真正查詢之前用“分詞器”**先分析 match 一下查詢字符:

B、如果用 match 下指定了一個確切值,在遇到數字,日期,布爾值或者 不分詞的字符串時,它將爲你搜索你給定的值:

{ "match": { "age": 26 }}
{ "match": { "date":"2014-09-01" }}
{ "match": { "public": true }}
{ "match": { "tag": "full_text"  }}

⑥、bool

bool 查詢可以用來合併多個條件查詢結果的布爾邏輯

包含以下幾個操作符

操作符 意義
must 多個查詢條件的完全匹配,相當於 and
must_not 多個查詢條件的相反匹配,相當於 not
should 至少有一個查詢條件匹配, 相當於 or

示例:

{
	"query":{
		"bool":{
			"must":{
				"range":{
					"age":{
						"gt":20,
						"lte":22
					}
				}
			},
			"must_not":{
				"term":{  ##注意不能匹配name,因爲name是text,可分詞的
					"age":21
				}
			}
		}
	}
}

⑦、filter

前面講過結構化查詢,Elasticsearch也支持過濾查詢,如term、range、match等。

示例:(查詢年齡爲20歲的用戶)

{
	"query":{
		"bool":{
			"filter":{
				"term":{
					"age":20
				}
			}
		}
	}
}

查詢和過濾的對比:

  • 一條過濾語句會詢問每個文檔的字段值是否包含着特定值。
  • 查詢語句會詢問每個文檔的字段值與特定值的匹配程度如何。
    • 一條查詢語句會計算每個文檔與查詢語句的相關性,會給出一個相關性評分 _score,並且 按照相關性對匹配到的文檔進行排序。 這種評分方式非常適用於一個沒有完全配置結果的全文本搜索。
  • 一個簡單的文檔列表,快速匹配運算並存入內存是十分方便的, 每個文檔僅需要1個字節。這些緩存的過濾結果集與後續請求的結合使用是非常高效的。
  • 查詢語句不僅要查找相匹配的文檔,還需要計算每個文檔的相關性,所以一般來說查詢語句要比 過濾語句更耗時,並且查詢結果也不可緩存。

建議:

做精確匹配搜索時,最好用過濾語句,因爲過濾語句可以緩存數據。

二、中文分詞

分詞就是指將一個文本轉化成一系列單詞的過程,也叫文本分析,在Elasticsearch中稱之爲Analysis。

指定分詞器進行分詞:

POST /_analyze
請求body:
{
    "analyzer":"standard",##標準分詞器
    "text":"hello world"##待分詞的內容
}

結果:
{
    "tokens": [
        {
            "token": "hello",
            "start_offset": 0,
            "end_offset": 5,
            "type": "<ALPHANUM>",
            "position": 0
        },
        {
            "token": "world",
            "start_offset": 6,
            "end_offset": 11,
            "type": "<ALPHANUM>",
            "position": 1
        }
    ]
}

指定索引分詞

POST /lee/_analyze

請求body:
{
    "analyzer":"standard",
    "filed":"hobby",
    "text":"聽音樂"
}

結果:
{
    "tokens": [
        {
            "token": "聽",
            "start_offset": 0,
            "end_offset": 1,
            "type": "<IDEOGRAPHIC>",
            "position": 0
        },
        {
            "token": "音",
            "start_offset": 1,
            "end_offset": 2,
            "type": "<IDEOGRAPHIC>",
            "position": 1
        },
        {
            "token": "樂",
            "start_offset": 2,
            "end_offset": 3,
            "type": "<IDEOGRAPHIC>",
            "position": 2
        }
    ]
}

中文分詞的難點在於,在漢語中沒有明顯的詞彙分界點,如在英語中,空格可以作爲分隔符,如果分隔不正確就會造成歧義。

常用中文分詞器,IK、jieba、THULAC等,推薦使用IK分詞器。

IK分詞器 Elasticsearch插件地址:https://github.com/medcl/elasticsearch-analysis-ik

IK分詞器安裝:

將elasticsearch-analysis-ik-6.5.4.zip 安裝到 es的plugin目錄的ik目錄下
1、創建ik目錄
cd /es/plugin
mkdir ik

2、解壓
unzip elasticsearch-analysis-ik-6.5.4.zip
(unzip命令不可用的,安裝yum install -y unzip zip)

3、啓動
su elsearch  ##切換elsearch用戶
cd es/bin
./elasticsearch -d

測試中文分詞:

POST /_analyze

#請求body
{
    "analyzer":"ik_max_word",
    "text":"我是中國人"
}

##結果:
{
    "tokens": [
        {
            "token": "我",
            "start_offset": 0,
            "end_offset": 1,
            "type": "CN_CHAR",
            "position": 0
        },
        {
            "token": "是",
            "start_offset": 1,
            "end_offset": 2,
            "type": "CN_CHAR",
            "position": 1
        },
        {
            "token": "中國人",
            "start_offset": 2,
            "end_offset": 5,
            "type": "CN_WORD",
            "position": 2
        },
        {
            "token": "中國",
            "start_offset": 2,
            "end_offset": 4,
            "type": "CN_WORD",
            "position": 3
        },
        {
            "token": "國人",
            "start_offset": 3,
            "end_offset": 5,
            "type": "CN_WORD",
            "position": 4
        }
    ]
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章