ElasticSearch 入門介紹
tags: 第三方 lucene
1. what Elastic Search(ES)是什么
全文檢索和lucene
全文檢索
優點:高效,准確,分詞
全文檢索允許用戶輸入一些關鍵字,從數據層中查找到所需要的信息
- 全文檢索和數據庫"LIKE"語句相比,遠比數據庫的開銷小,因為檢索過程全部從通過檢索文件完成,因此效率非常高。
- 在全文檢索領域,用戶輸入的搜索信息叫做關鍵字,而全文檢索系統把海量信息按照這些關 鍵字進行結構化處理,把文章打散成段落、文字,最后,按關鍵字對文章的數據進行分類。這個處理后的數據文本叫做檢索文件,檢索文件往往比實際數據小得多,但它的數據所包含的信息量損失卻非常小。當用戶輸入一個關鍵字時,全文檢索引擎可以很快地定位到相關文本。
lucene
lucene是一個是一個開源的全文檢索引擎庫,Apache基金會贊助項目.無論在開源還是專有領域,Lucene可以被認為是迄今為止最先進、性能最好的、功能最全的搜索引擎庫(《Elastic Search 權威指南》)。lucene有很多優點,包括:它的文本分析器可以定制,檢索文件存儲方式可以定制,查詢引擎也有不同的可選方案.此外,它提供一套非常強大的API接口,使客戶用起來很方便.
Elastic Search
lucene是一個非常強大的全文檢索引擎庫,但是遺憾的是,它是一個庫,想要使用它,你必須使用Java來作為開發語言並將其直接集成到你的應用中,更糟糕的是,Lucene非常復雜,你需要深入了解檢索的相關知識來理解它是如何工作的。
Elasticsearch也使用Java開發並使用Lucene作為其核心來實現所有索引和搜索的功能,但是它的目的是通過簡單的RESTful API來隱藏Lucene的復雜性,從而讓全文搜索變得簡單。
2. why 為什么選擇ES,ES有什么優點
- ES以Lucene為核心實現了索引和搜索功能,它擁有着全文搜索的優點,准確高效的查詢和分詞處理數據源。
- ES封裝了Lucene,對用戶隱藏了Lucene的復雜知識,用戶只需要了解ES提供的RESTful API就可以使用全文檢索而不需要去了解Lucene的眾多基本知識
- ES是一個單獨的程序,通過http請求就可以操作,兩個不同的項目可以同時使用訪問ES
- ES支持分布式,可以擴展到上百台服務器,處理PD級結構化或者非結構話數據。
3. when or where什么地方使用elastic
- 字段文本量較大會比較大,用數據庫的like效率會明顯感覺出來
- 模糊查詢時候需要對關鍵詞進行分詞而不是只是簡單的匹配
4. how 如何使用ES
1.ES的安裝
ES的安裝很簡單,即裝即用.去官網下載ES[下載地址][1],在任何配置了java運行環境的電腦上后將壓縮文件解壓縮即可.
解壓后進入解壓下的bin文件夾,啟動elasticserach.bat(windows系統),如下:
![啟動目錄][2]
啟動后進入cmd窗口,如下圖所示即成功啟動:
![此處輸入圖片的描述][3]
然后我們打開瀏覽器訪問以下ES,輸入http:localhost:9200,如下即為成功運行:
![此處輸入圖片的描述][4]
2. ES數據存儲的介紹
ES是數據存儲是面向文檔的,數據的存儲形式是以對象的形式(JSON)來存儲的,而不是像關系型數據庫一樣把數據抽象一行行記錄去適應數據庫.同時在存儲的時候,ES還會索引每條數據內容使得每條內容可以被搜索.
ES存儲的相關概念與傳統關系型數據庫的對比:
其中的fields(字段)就相當於關系型數據庫的列;多個字段組成一個Document(文檔)相當於關系型數據庫的行(一條數據);相同類型的Documents組成一個type(類型),相當於關系型數據庫的一張數據表;而多個types就會組成一個index(索引),相當於關系型數據的數據庫.關系對應如下:
Relational DB -> Databases -> Tables -> Rows -> Columns
Elasticsearch -> Indices -> Types -> Documents -> Fields
1. index
index的兩個概念介紹:
- 索引(名詞) 如上文所述,一個索引(index)就像是傳統關系數據庫中的數據庫,它是相關文檔存儲的地方,index的復數是indices 或indexes。
- 索引(動詞) 「索引一個文檔」表示把一個文檔存儲到索引(名詞)里,以便它可以被檢索或者查詢。這很像SQL中的INSERT關鍵字,差別是,如果文檔已經存在,新的文檔將覆蓋舊的文檔。
2.index,type的建立
ES對提供的REST ful接口,任何對數據的操作和查詢都可以通過想ES發送HTTP請求來完成.關於RESTful協議的相關知識可以參照一下[RESTful API 設計指南][5],了解一下RESTful協議能共更容易理解ES提供的接口.
現在我們要建立一個所以,按照ES提供的RESTful接口,我們應該對ES發一個PUT請求,如下:
需要注意的是index名字里的字母都必須是小寫.
如果成功,我們會獲取如下的返回結果:
json
{
"acknowledged": true
}
然后我們再向ES發送GET請求,來獲取我們剛剛創建的testindex的屬性:
> GET http://localhost:9200/testindex
結果如下:
```json```
{
"testindex": {
"aliases": {},
"mappings": {},
"settings": {
"index": {
"creation_date": "1465748163064",
"uuid": "uYyeZC_bQ1Olwe8lDrqXaw",
"number_of_replicas": "1",
"number_of_shards": "5",
"version": {
"created": "2030399"
}
}
},
"warmers": {}
}
}
相關的tpye,document最簡單的增刪查改也都可以通過PUT GET POST DELET 幾個常用的請求來完成,這里就不做詳細的介紹了,詳細的可以查看[ElasticSearch權威指南中文版][6]了解一下.
3.mapping
mapping可以理解為描述index/type以及field的元數據,通過mapping我們可以來設置index/type/field.
單獨的生成或者更新type的mappiing
URL: PUT http://localhost:9200/wisdomhr/_mapping/basejob/
json
{
"properties": {
"activateTiem": {
"type": "date",
"format": "yyyy-MM-dd"
},
"title": {
"type": "string",
"boost": 10,
"store": true,
"analyzer": "ik"
}
}
}
參考文檔:[更新mapping][7]
通常我們需要在構建mapping的時候來設置一些常用的屬性,主要是包括字段的類型,是否被分詞,分詞使用的分詞器,分詞時候自己所占的比重等,如下:
> - type:類型,包括date,string,boolean,integer等,跟常用的類型跟java很相似,同時也有array類型可以直接存儲數組.
- analyzer: 分詞器,這個屬性會決定你在索引和查找階段所使用的分詞器;如果沒有特別指出,analyzer定義的分詞器可以用在索引和查找階段.也可以單獨通過search_analyzer來指定作為查找時的分詞器.
- boost:這個屬性會決定你在分詞的時候該字段的權重,在搜索的時候,默認會按照每條數據的評分來進行排序,而這個權重就會用基礎得分*權重來決定最后的得分.
- format:當數據類型是date的時候,通過format來設置時間的格式
其余的更多的類型可以參考官方文檔[mapping][8]
### 3 ES的索引過程
ES為了能夠更好的進行查詢,在保存數據之前,都會對數據進行索引(動詞),那么在這個所以過程里面,ES都做了什么?
####a. 文檔分析(analysis)
ES會對文檔進行一系列的操作和處理,是他們能夠更容易被搜索.它包括如下的幾個過程:
##### 字符過濾器(character filter)處理
字符過濾器的主要工作室對原始數據的特殊字符進行過濾和處理,比如去除掉文檔中的html標簽,把&變成單詞"and"等等
##### 分詞器(tokenizer)處理
所謂的分詞器就是指某種算法,這個算法會按照自己的對文檔(經過字符過濾器處理過的文檔)進行處理,提取若干的單詞,這些被提取出來的單詞就成為詞元(**Token**),顧名思義,這些詞元已經是最小的不能分割了.
##### 標記過濾(token filters)處理
標記過濾(**token filters**)會對詞元(**Token**)進行進一步的處理,處理細節包括一些將單詞的大寫變成小寫、去除英語中的連詞或者介詞(to,for,of等)、去除漢語中的語氣詞等、進一步保證最后剩下的單詞都是有明確的自然語義的詞,這些剩下的單詞就被稱作詞(**term**)
到此整個文檔分析階段就結束了
#### b.倒排索引
Elasticsearch使用一種叫做倒排索引(inverted index)的結構來做快速的全文搜索。倒排索引由在文檔中出現的唯一的單詞列表,以及對於每個單詞在文檔中的位置組成。
分詞結束后,es會根據分詞的結果詞(**term**)構建出一個倒序索引用於快速查詢.
#### c.相關度評分
在索引階段es做的另一件事就是計算不同詞(**term**)在不同文檔中的相關度評分,這個評分會用在之后查詢時候的查詢結果的排序上,默認的會將相關度較高的文檔排在最前面
### 4查詢的簡單介紹
#### a.URL控制的簡單查詢(通過GET請求中的URL參數控制)
##### 1.空查詢
當我們需要查詢的時候,最簡單的,我們可以向ES發送一個get請求,構造一個查詢的url,如下
> GET http://localhost:9200/my_index/_search
默認的,會ES會發揮my_index下的所有數據,如果數據過多ES會自動進行分頁處理顯示一部分數據(默認是10個).會返回如下形式的結果:
```json```
{
"took": 62,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 1,
"hits": [
{
"_index": "my_index",
"_type": "my_type",
"_id": "1",
"_score": 1,
"_source": {
"title": "Some short title",
"date": "2015-01-01",
"content": "A very long content field..."
}
}
]
}
}
2.分頁查詢
如果我們需要分頁功能,就需要在get請求的url中加入size和from倆個參數,size表示分頁大小,from表示開始位置,如下:
3.模糊查詢
如果需要模糊查詢,可以在URL參數中附加一個q(query的意思)參數,如下:
GET http://localhost:9200/my_index/_search?q=title:Some
意思是查詢my_index下title中包含"Some"的數據.
b.結構體查詢(構造json格式的body進行查詢)
通過URL參數控制,我們只能進行一下簡單的查詢,但是在實際過程中,我們通產的查詢條件都要更加復雜,這時候我們就需要使用另一種適用於復雜查詢的方式--結構體查詢.
按照rest ful協議,我們也是應該想ES發送GET請求來獲取ES中的數據,但是在日常開發中,很多地方都不允許在GET請求上附加body數據,因此ES中我們也可以通過POST來獲取ES中的數據.發送POST請求的時候,除了請求方式之外,URL和數據體body都跟GET的完全相同(以下都以POST請求為例)
1.body常用屬性
- query
query部分是查詢的核心部分,提供了包括模糊查詢,精確過濾,多查詢條件聯合的復雜查詢模式.例如:
json
{
"query": {
"bool": {
"must": [
{ "match": { "title": "Search" }},
{ "match": { "content": "Elasticsearch" }}
],
"filter": [
{ "term": { "status": "published" }}
]
}
}
}
上面的body的大意是要搜索title中即包含"search"並且content中包含"elasticsearch",同時status為"published"數據.關於query有專門的queryDSL來規定query的形式,在后面文檔中會介紹.
- from/size 分頁
from/size與url中相同,同樣是用來進行分頁的參數,如下:
```json```
{
"from" : 0, "size" : 10,
"query" : {
"term" : { "user" : "kimchy" }
}
}
- sort 排序
sort部分會按照給定的規則對搜索結果進行排序,如
json
{
"sort" : [
{ "post_date" : {"order" : "asc"}},
{ "price" : {"order" : "asc"}}
],
"query" : {
"term" : { "user" : "kimchy" }
}
}
如上,sort會優先按照post_date進行正序排序,當post_date相同的時候在按照price進行正序排序.特別的在日常的查詢中,查詢結果通常都會有相關的_scroe評分,默認的,ES會按照_score對搜索結果進行性倒敘排序,是的相關度最高的文檔在最前方顯示.
- fields
fields字段會對文檔進行過濾,是查詢結果只返回指定的字段,例如:
當不是用fields字段的時候,body如下:
```json```
{
"query":{
"match":{"title":"some"}
}
}
查詢的返回結果默認的會包含所有保存的字段:
json
{
"_index": "my_index",
"_type": "my_type",
"_id": "1",
"_score": 0.15342641,
"_source": {
"title": "Some short title",
"date": "2015-01-01",
"content": "A very long content field..."
}
}
當我們使用fields的時候,body如下:
```json```
{
"fields":["title"],
"query":{
"match":{"title":"some"}
}
}
返回結果的數據部分指揮顯示title字段:
json
{
"_index": "my_index",
"_type": "my_type",
"_id": "1",
"_score": 0.15342641,
"fields": {
"title": [
"Some short title"
]
}
}
- highlight
highlight部分用來控制搜索結果的高亮顯示.很多時候,當我們進行全文檢索的時候都會對搜索結果中的搜索關鍵字進行高亮以突出顯示,這時候就需要用到highlight,如發送如下body的請求:
```json```
{
"query":{
"match":{"title":"some"}
},
"highlight" : {
"pre_tags" : ["<b>"], //設置高亮的前 后html標簽
"post_tags" : ["</b>"],
"fields" : {
"title" : {}
}
}
}
在返回的數據部分,我們會得到高亮的字段,如下
json
{
"_index": "my_index",
"_type": "my_type",
"_id": "1",
"_score": 0.15342641,
"_source": {
"title": "Some short title",
"date": "2015-01-01",
"content": "A very long content field..."
},
"highlight": {
"title": [
"Some short title" //這里是高亮顯示的關鍵字
]
}
}
##### 2. query
ES的主要任務是通過全文搜索引擎進行全文搜索,在ES提供的接口中,這部分任務主要由請求體中的query部門來完成的.而query DSL就是來解釋query的用法.
[1]: https://www.elastic.co/downloads/elasticsearch
[2]: http://7xsvhr.com1.z0.glb.clouddn.com/ES/document/bin.jpg
[3]: http://7xsvhr.com1.z0.glb.clouddn.com/ES/document/console.jpg
[4]: http://7xsvhr.com1.z0.glb.clouddn.com/page.jpg
[5]: http://www.ruanyifeng.com/blog/2014/05/restful_api.html
[6]: http://es.xiaoleilu.com/010_Intro/25_Tutorial_Indexing.html
[7]: https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-put-mapping.html#merging-conflicts
[8]: https://www.elastic.co/guide/en/elasticsearch/reference/current/analyzer.html