1. 程式人生 > >ES(ElasticSearch)分散式全文搜尋引擎介紹及使用方式

ES(ElasticSearch)分散式全文搜尋引擎介紹及使用方式

1.什麼是ES

**ES** 全稱 **ElasticSearch** 是一種分散式全文搜尋引擎,基於Lucene(全文搜尋框架)開發而來。
Lucene是公認的迄今為止的最好用的搜尋引擎庫,但是他所提供的API對於我們使用者來說,是非常苦惱的,常要花費大量時間去熟悉學習。ES的出現就很好的解決了這個問題,良好的封裝,易用的API,鏈式書寫方式,開瓶即飲。

2.ES特點

**ES** 雖然是以Lucene核心庫開發的,但是卻不是以它作為核心,**ES** 的貼點體現在:
	*分散式實時檔案儲存,每個欄位皆能索引* 
	*叢集,可擴充套件(理論上無上限)*
	*高度整合的服務(RESTful風格的API,各語言客戶端)*
	*易學易用,開瓶即飲*

3.ES安裝

3.1下載

[ES官方下載地址:](https://www.elastic.co/downloads/elasticsearch)
ES安裝環境只依賴JDK,以5.2.2版本為例,下載對應的檔案即可

3.2安裝

將壓縮包解壓,然後在解壓後的目錄下找到*bin*資料夾,點選名為**elasticsearch.bat** 檔案執行。
測試是否安裝成功:訪問:http://localhost:9200/ 
![安裝成功:](https://img-blog.csdnimg.cn/2018110517350745.png)

**注意**:
	如果本機記憶體過小,或者磁碟空間不足會啟動失敗,手動修改*config*資料夾下**jvm.options**檔案中的引數。
	開啟**jvm.options**檔案,搜尋-Xms,得到結果如下:
################################################################
## IMPORTANT: JVM heap size
################################################################
##
## You should always set the min and max JVM heap
## size to the same value. For example, to set
## the heap to 4 GB, set:
##
## -Xms4g
## -Xmx4g
##
## See https://www.elastic.co/guide/en/elasticsearch/reference/current/heap-size.html
## for more information
##
################################################################

# Xms represents the initial size of total heap space
# Xmx represents the maximum size of total heap space
#  '#'代表的是註釋, -Xms 最小佔用記憶體 -Xm最大佔用記憶體 如果修改,預設啟動時為2gb 這裡可以修改一下
-Xms200m
-Xmx200m

輔助管理工具Kibana5

這裡介紹一款輔助學習工具,避免了使用cmd的尷尬場景
[Kibana5.2.2下載地址:](https://www.elastic.co/downloads/kibana)
  1. 解壓並編輯config/kibana.yml,設定elasticsearch.url 的值為已啟動的ES
  2. 啟動Kibana5 : bin\kibana.bat
  3. 選單: Discover:視覺化查詢分析器 Visualize:統計分析圖表 Dashboard:自定義主面板(新增圖表) Timelion:Timelion是一個kibana時間序列展示元件(暫時不用) Dev Tools :Console(同CURL/POSTER,操作ES程式碼工具,程式碼提示,很方便) Management:管理索引庫(index)、已儲存的搜尋和視覺化結果(save objects)、設定 kibana 伺服器屬性

ES使用

ES資料管理

ES文件
ES是面向文件(document oriented)的,這意味著它可以儲存整個物件或文件(document)。然而它不僅僅是儲存,還會索引(index)每個文件的內容使之可以被搜尋。在ES中,你可以對文件(而非成行成列的資料)進行索引、搜尋、排序、過濾。
ES使用Javascript物件符號(JavaScript Object Notation),也就是JSON,作為文件序列化格式。JSON現在已經被大多語言所支援,而且已經成為NoSQL領域的標準格式。
ES儲存的一個員工文件的格式示例:
	{
		_index : “crm”,
		_type : “user”,就
		_id : 1, 
		_source : {
		"email": "[email protected]",
		"name": "倪先華",
		"info": {
		     "addr": "四川省成都市",
		     "age": 30,
		     "interests": [ "美食", "美女" ]
		},
		"join_date": "2016-06-01"
		}
	}
儘管原始的 employee物件很複雜,但它的結構和物件的含義已經被完整的體現在JSON中了,在ES中將物件轉化為JSON並做索引要比在表結構中做相同的事情簡單的多。
文件的必須三個節點:
  1. _index : “crm”, 文件儲存位置(索引)
  2. _type : “user”,文件對映型別
  3. _id : 1,文件唯一標識(可以自定義也可以自動生成)
ES文件的CRUD
以員工物件為例,,類比傳統的資料庫來看:
  1. 關係資料庫(MYSQL) -> 資料庫DB-> 表TABLE-> 行ROW-> 列Column
  2. Elasticsearch -> 索引庫Indices -> 型別Types -> 文件Documents -> 欄位Fields

ES叢集可以包含多個索引(indices)(資料庫),每一個索引庫中可以包含多個型別(types)(表),每一個型別包含多個文件(documents)(行),然後每個文件包含多個欄位(Fields)(列)。

//這裡使用Kibana5編寫的
# 建立crm
PUT crm

# 儲存資料
POST crm/user/1
{
  "age" : 1,
  "name": "fq"
}

# 取值 (_source檢視源資料)
GET crm/user/1

//展示結果
{
  "_index": "crm",
  "_type": "user",
  "_id": "1",
  "_version": 3,
  "found": true,
  "_source": {
    "age": 1,
    "name": "fq"
  }
}


/*
這個API 似乎 允許你修改文件的區域性,但事實上Elasticsearch
遵循與之前所說完全相同的過程,這個過程如下:
1. 從舊文件中檢索JSON
2. 修改它
3. 刪除舊文件
4. 索引新文件
*/
# 存在修改,不存在建立(先刪除在建立)
POST crm/user/1
{
  "age" : 2,
  "name": "fqq"
}
# 取值(_source只看源資料)
GET crm/user/1/_source

//展示結果
{
  "age": 2,
  "name": "fqq"
}


# 刪除文件
DELETE crm/user/1
//查詢會查詢不到,沒有結果返回

# 獲取所有文件
GET _search

# 分頁查詢
/*
	和SQL使用 LIMIT  關鍵字返回只有一頁的結果一樣,Elasticsearch接受 from  和 size  引數:
size  : 每頁條數,預設 10
from  : 跳過開始的結果數,預設 0
*/
GET _search?size=5&from=10

DSL查詢與過濾

概念

由ES提供豐富且靈活的查詢語言叫做DSL查詢(Query DSL),它允許你構建更加複雜、強大的查詢。

DSL(Domain Specific Language特定領域語言)以JSON請求體的形式出現。

     //查詢字串模式:同樣是使用Kibana5
     GET itsource/employee/_search?q=fullName:倪先華
     DSL模式:
     GET itsource/employee/_search
     {
     "query" : {
        "match" : {
        		"fullName" : "倪先華"
  		}
     	}
     }

DSL查詢

使用DSL查詢,必須要傳遞query引數給ES。

	GET _search
	{"query": YOUR_QUERY_HERE}
	# 例項一個完整查詢
	/*
		查詢公司員工性別為女的員工,並按照加入時間降序、年齡升序排列,最終返回第21條至30條資料(只返回名字、年齡和email欄位)
	*/
	GET itsource/employee/_search
	{
	"query": {
	   "match": {"sex":"女"}
	},
	"from": 20, 
	"size": 10,
	" _source": ["fullName", "age", "email"],
	"sort": [{"join_date": "desc"},{"age": "asc"}]
	}

DSL過濾

DSL過濾語句和DSL查詢語句非常相似,但是它們的使用目的卻不同: DSL過濾查詢文件的方式更像是對於我的條件“有”或者“沒有”,而DSL查詢語句則像是“有多像”。 DSL過濾和DSL查詢在效能上的區別:

  • 過濾結果可以快取並應用到後續請求。
  • 查詢語句同時匹配文件,計算相關性,所以更耗時,且不快取。
  • 過濾語句可有效地配合查詢語句完成文件過濾。

原則上,使用DSL查詢做全文字搜尋或其他需要進行相關性評分的場景,其它全用DSL過濾

使用方式

{
	"query": {
	   "bool": {
	   	# 必須條件
	          "must": [
				{"match": {"description": "search" }}
			],
		# 過濾條件	
	           "filter": {
	               "term": {"tags": "lucene"}
	           }
	    }
	}
}

//① 全匹配(match_all)
//普通搜尋(匹配所有文件):
{
	"query" : {
		"match_all" : {}
	}
}
//如果需要使用過濾條件(在所有文件中過濾,紅色部分預設可不寫):
{
	"query" : {
		"bool" : {
		"must" : [{
			"match_all":{}
		}],
		"filter":{....}
		}
	}
}
/*② 標準查詢(match和multi_match)
match查詢是一個標準查詢,不管你需要全文字查詢還是精確查詢基本上都要用到它。
如果你使用match查詢一個全文字欄位,它會在真正查詢之前用分析器先分析查詢字元:*/
{
	"query": {
		"match": {
			"fullName": "Steven King"
		}
	}
}
//上面的搜尋會對Steven King分詞,並找到包含Steven或King的文件,然後給出排序分值。

//如果用 match  下指定了一個確切值,在遇到數字,日期,布林值或者 not_analyzed的字串時,它將為你搜索你給定的值,如:
{ "match": { "age": 26 }}
{ "match": { "date": "2014-09-01" }}
{ "match": { "public": true }}
{ "match": { "tag": "full_text" }}

//multi_match  查詢允許你做 match查詢的基礎上同時搜尋多個欄位:
{
"query":{
"multi_match": {
"query": "Steven King",
"fields": [ "fullName", "title" ]
}
}
}
/*上面的搜尋同時在fullName和title欄位中匹配。
提示:match一般只用於全文欄位的匹配與查詢,一般不用於過濾。*/

//③單詞搜尋與過濾(Term和Terms)
{
	"query": {
	"bool": {
		"must": { 
			"match_all": {} 
		}, 
		"filter": { 
			"term": { 
				"tags": "elasticsearch" 
				} 
			} 
		} 
	}
}
//Terms搜尋與過濾
{
	"query": {
		"terms": {
		"tags": ["jvm", "hadoop", "lucene"],
		"minimum_match": 2
		}
	}
}
//minimum_match:至少匹配個數,預設為1

/*④ 組合條件搜尋與過濾(Bool)
組合搜尋bool可以組合多個查詢條件為一個查詢物件,查詢條件包括must、should和must_not。
例如:查詢愛好有美女,同時也有喜歡遊戲或運動,且出生於1990-06-30及之後的人。*/
{
	"query": {
		"bool": {
			"must": [{"term": {"hobby": "美女"}}],
			"should": [{"term": {"hobby": "遊戲"}},{"term": {"hobby": "運動"}}],
			"must_not": [{"range" :{"birth_date":{"lt": "1990-06-30"}}} ],
			 "filter": [...],
			"minimum_should_match": 1
		}
	}
}
//提示: 如果 bool 查詢下沒有must子句,那至少應該有一個should子句。但是 如果有 must子句,那麼沒有 should子句也可以進行查詢。
/*
⑤ 範圍查詢與過濾(range)
range過濾允許我們按照指定範圍查詢一批資料:*/
{
	"query":{
		"range": {
			"age": {
				"gte": 20,
				"lt": 30
			}
		}
	}
}
//上例中查詢年齡大於等於20並且小於30。
//gt:>    gte:>=   lt:<  lte:<=

/*⑥ 存在和缺失過濾器(exists和missing)*/
{
	"query": {
		"bool": {
			"must": [{
				"match_all": {}
			}],
			"filter": {
				"exists": { "field": "gps" }
			}
		}
	}
}
/*提示:exists和missing只能用於過濾結果。
⑦ 前匹配搜尋與過濾(prefix)
和term查詢相似,前匹配搜尋不是精確匹配,而是類似於SQL中的like ‘key%’*/
{
	"query": {
		"prefix": {
		"fullName": "倪"
		}
	}
}
//上例即查詢姓倪的所有人。

/*⑧ 萬用字元搜尋(wildcard)
使用*代表0~N個,使用?代表1個。*/
{
	"query": {
		"wildcard": {
		"fullName": "倪*華"
		}
	}
}