歡迎訪問本人博客:http://wangnan.tech
Elasticsearch是一個可伸縮的開源全文搜索和分析引擎,它使你可以快速且接近實時的去保存,查詢和分析海量的數據,他的潛在應用場景是作為一些有復雜搜索功能和需求的應用的搜索引擎
簡介
Elasticsearch是一個基于Apache Lucene(TM)的開源搜索引擎。無論在開源還是專有領域,Lucene可以被認為是迄今為止最先進、性能最好的、功能最全的搜索引擎庫。
但是,Lucene只是一個庫。想要使用它,你必須使用Java來作為開發語言并將其直接集成到你的應用中,更糟糕的是,Lucene非常復雜,你需要深入了解檢索的相關知識來理解它是如何工作的。Elasticsearch也使用Java開發并使用Lucene作為其核心來實現所有索引和搜索的功能,但是它的目的是通過簡單的RESTful API來隱藏Lucene的復雜性,從而讓全文搜索變得簡單。
與關系型數據庫對比
Relational DB -> Databases -> Tables -> Rows -> Columns
Elasticsearch -> Indices -> Types -> Documents -> Fields
Elasticsearch集群可以包含多個索引(indices)(數據庫),每一個索引可以包含多個類型(types)(表),每一個類型包含多個文檔(documents)(行),然后每個文檔包含多個字段(Fields)(列)
基礎概念
near realtime(NRT)
es是一個接近實時的搜索平臺,這意味著你查詢一個文檔的時候有一個延時。大約一秒
cluster
集群是一個或多個節點(服務器)的集合在一起,保存所有的數據,聯合所有節點一起提供查詢能力。
一個集群有一個唯一的名字,默認是“elasticsearch",集群名很重要,因為集群節點加入集群的唯一方式是根據這個名字。
node
節點的默認名字是漫威的一個角色,默認加入集群elasticsearch
index
索引是一系列具有相似特點文檔的集合
實際上,索引只是一個用來指向一個或多個分片(shards)的“邏輯命名空間(logical namespace)
「索引」含義的區分
你可能已經注意到索引(index)這個詞在Elasticsearch中有著不同的含義,所以有必要在此做一下區分:
索引(名詞) :如上文所述,一個索引(index)就像是傳統關系數據庫中的數據庫,它是相關文檔存儲的地方,index的復數是indices 或indexes。
索引(動詞) :「索引一個文檔」表示把一個文檔存儲到索引(名詞)里,以便它可以被檢索或者查詢。這很像SQL中的INSERT關鍵字,差別是,如果文檔已經存在,新的文檔將覆蓋舊的文檔。
倒排索引 傳統數據庫為特定列增加一個索引,例如B-Tree索引來加速檢索。Elasticsearch和Lucene使用一種叫做倒排索引(inverted index)的數據結構來達到相同目的。
Type
索引中,類型是一種邏輯的分類,它的意義由使用者來賦予
mapping
每個類型(type)都有自己的映射(mapping)或者結構定義,就像傳統數據庫表中的列一樣。所有類型下的文檔被存儲在同一個索引下,但是類型的映射(mapping)會告訴Elasticsearch不同的文檔如何被索引
Elasticsearch支持以下簡單字段類型:
類型 表示的數據類型
String string
Whole number byte, short, integer, long
Floating point float, double
Boolean boolean
Date date
document
文檔是搜索信息的基本單元,用json表達,文檔必須被包含于一個type中
文檔 ID文檔唯一標識由四個元數據字段組成:
_id:文檔的字符串 ID
_type:文檔的類型名
_index:文檔所在的索引
_uid:_type 和 _id 連接成的 type#id
默認情況下,_uid 是被保存(可取回)和索引(可搜索)的。_type 字段被索引但是沒有保存,_id 和_index 字段則既沒有索引也沒有儲存,它們并不是真實存在的。
shards&replicas
es提供能力,讓你把index分成好幾個部分,叫做分片,當你創建索引的時候,你可以簡單的定義分片的個數,每個分片本身是一個獨立的功能齊全的“索引”,可以被放到任何的集群節點中
分片的意義:
1.可以水平分割和擴展數據
2.可以把操作分配給多個分區,提高性能
es允許你制作一個或多個分片的副本。叫做復制分片
復制分片的意義:
1、他提供了高可用性,副本和原始分區不處于一個節點中。
2.他提高了性能,因為搜索可以在任何分區上允許。
每一個分片是一個lucene索引,每個Lucene實例有一個最大的存放文檔的數量。這個數量是2417483519
analysis
分析也稱分詞
Elasticsearch中的數據可以大致分為兩種類型:
確切值 及 全文文本。
確切值是確定的,正如它的名字一樣。比如一個date或用戶ID,也可以包含更多的字符串比如username或email地址。
全文文本常常被稱為非結構化數據,而對于全文數據的查詢來說,卻有些微妙。我們不會去詢問這篇文檔是否匹配查詢要求?。 但是,我們會詢問這篇文檔和查詢的匹配程度如何?。換句話說,對于查詢條件,這篇文檔的相關性有多高?
為了方便在全文文本字段中進行這些類型的查詢,Elasticsearch首先對文本分析(analyzes),然后使用結果建立一個倒排索引。
分析(analysis)機制用于進行全文文本(Full Text)的分詞,以建立供搜索用的反向索引。
分析(analysis)是這樣一個過程:
首先,標記化一個文本塊為適用于倒排索引單獨的詞(term)
然后標準化這些詞為標準形式,提高它們的“可搜索性”或“查全率”
這個工作是分析器(analyzer)完成的。一個分析器(analyzer)只是一個包裝用于將三個功能放到一個包里:
字符過濾器
1.首先字符串經過字符過濾器(character filter),它們的工作是在標記化前處理字符串。字符過濾器能夠去除HTML標記,或者轉換"&"為"and"。
分詞器
2.下一步,分詞器(tokenizer)被標記化成獨立的詞。一個簡單的分詞器(tokenizer)可以根據空格或逗號將單詞分開(譯者注:這個在中文中不適用)
標記過濾
3.最后,每個詞都通過所有標記過濾(token filters),它可以修改詞(例如將"Quick"轉為小寫),去掉詞(例如停用詞像"a"、"and"、"the"等等),或者增加詞(例如同義詞像"jump"和"leap")
index參數控制字符串以何種方式被索引。它包含以下三個值當中的一個:
analyzed首先分析這個字符串,然后索引。換言之,以全文形式索引此字段。not_analyzed索引這個字段,使之可以被搜索,但是索引內容和指定值一樣。不分析此字段。no不索引這個字段。這個字段不能為搜索到。
string類型字段默認值是analyzed。如果我們想映射字段為確切值,我們需要設置它為not_analyzed:
{
"tag": {
"type": "string",
"index": "not_analyzed"
}
}其他簡單類型(long、double、date等等)也接受index參數,但相應的值只能是no和not_analyzed,它們的值不能被分析。
Elasticsearch提供很多開箱即用的字符過濾器,分詞器和標記過濾器。這些可以組合來創建自定義的分析器以應對不同的需求。
string類型的字段,默認的,考慮到包含全文本,它們的值在索引前要經過分析器分析,并且在全文搜索此字段前要把查詢語句做分析處理。
對于string字段,兩個最重要的映射參數是index和analyer。
highlight
很多應用喜歡從每個搜索結果中高亮(highlight)匹配到的關鍵字,這樣用戶可以知道為什么這些文檔和查詢相匹配。
score
每個節點都有一個_score字段,這是相關性得分(relevance score),它衡量了文檔與查詢的匹配程度。默認的,返回的結果中關聯性最大的文檔排在首位;這意味著,它是按照_score降序排列的。這種情況下,我們沒有指定任何查詢,所以所有文檔的相關性是一樣的,因此所有結果的_score都是取得一個中間值1
max_score指的是所有文檔匹配查詢中_score的最大值。
refresh
默認情況下,每個分片每秒自動刷新一次。這就是為什么說Elasticsearch是近實時的搜索了:文檔的改動不會立即被搜索,但是會在一秒內可見。
sort
排序
默認情況下,結果集會按照相關性進行排序 -- 相關性越高,排名越靠前
字段值排序:
按時間排序
GET /_search
{
"query" : {
"filtered" : {
"filter" : { "term" : { "user_id" : 1 }}
}
},
"sort": { "date": { "order": "desc" }}
}
返回:
"hits" : {
"total" : 6,
"max_score" : null, <1>
"hits" : [ {
"_index" : "us",
"_type" : "tweet",
"_id" : "14",
"_score" : null, <1>
"_source" : {
"date": "2014-09-24",
...
},
"sort" : [ 1411516800000 ] <2>
},
...
}
_score 是比較消耗性能的, 而且通常主要用作排序 -- 我們不是用相關性進行排序的時候,就不需要統計其相關性
字段值默認以順序排列(從小到大 ),而 _score 默認以倒序排列。
緩存
過濾器是怎么計算的。它們的核心是一個字節集來表示哪些文檔符合這個過濾器。Elasticsearch 主動緩存了這些字節集留作以后使用。一旦緩存后,當遇到相同的過濾時,這些字節集就可以被重用,而不需要重新運算整個過濾。
集很“聰明”:他們會增量更新。你索引中添加了新的文檔,只有這些新文檔需要被添加到已存的字節集中,而不是一遍遍重新計算整個緩存的過濾器。過濾器和整個系統的其他部分一樣是實時的,你不需要關心緩存的過期時間。
安裝
- 首先需要依賴java7以上版本
- curl -L -O https://download.elastic.co/elasticsearch/release/org/elasticsearch/distribution/tar/elasticsearch/2.3.3/elasticsearch-2.3.3.tar.gz
tar -xvf elasticsearch-2.3.3.tar.gz
cd elasticsearch-2.3.3/bin
./elasticsearch - 可以在啟動的時候重寫集群和節點的名字
./elasticsearch --cluster.name my_cluster_name --node.name my_node_name - 默認,es使用9200端口提供 restapi訪問
安裝配置:
config/elasticsearch.yml
network : host : 10.0.0.4
path: logs: /var/log/elasticsearch
data: /var/data/elasticsearch
cluster: name: <NAME OF YOUR CLUSTER>
node: name: <NAME OF YOUR NODE>
瀏覽你的集群
es提供了豐富的restapi用于和集群直接通信包括:
1.檢查集群,節點,索引,狀態和統計
2.管理集群,節點,索引數據和與元數據
3.對索引curd
4.使用高級搜索功能,比如分頁,排序,過濾,腳本,聚合和其他很多
集群健康:
curl 'localhost:9200/_cat/health?v'
返回
epoch timestamp cluster status node.total node.data shards pri relo init unassign
1394735289 14:28:09 elasticsearch green 1 1 0 0 0 0 0
顏色 意義
green 所有主要分片和復制分片都可用
yellow 所有主要分片可用,但不是所有復制分片都可用
red 不是所有的主要分片都可用
列舉出所有索引:
curl'localhost:9200/_cat/indices?v'
創建一個索引:
curl -XPUT 'localhost:9200/customer?pretty'
創建一個文檔:
curl -XPUT 'localhost:9200/customer/external/1?pretty'-d '{ "name": "John Doe"}'
刪除一個索引:
curl -XDELETE 'localhost:9200/customer?pretty'
修改你的數據
替代你的文檔:
curl -XPUT 'localhost:9200/customer/external/1?pretty'-d '
{ "name": "John Doe" }'
curl -XPUT 'localhost:9200/customer/external/1?pretty'-d '
{ "name": "Jane Doe" }'
如果指定了id,去創建,之前的那個會被覆蓋
如果沒有指定id,es會隨機的生成一個id
更新文檔:
es并不會真正的更新文檔,當我們進行更新操作的時候,es刪除原來的文檔,
然后添加一個新的文檔。
更新文檔也可以使用腳本,動態腳本在1.4.3版本默認被禁用
curl -XPOST 'localhost:9200/customer/external/1/_update?pretty'-d '
{ "script" : "ctx._source.age += 5" }'
ctx._source指向要被修改的文檔
es后續將會提供能力,類似sql中的 UPDATE-WHERE statement
刪除文檔
curl -XDELETE 'localhost:9200/customer/external/2?pretty'
delete-by-query 插件可以刪除滿足要求的一類文檔
批量操作:
curl -XPOST 'localhost:9200/customer/external/_bulk?pretty' -d '
{"index":{"_id":"1"}}
{"name": "John Doe" }
{"index":{"_id":"2"}}
{"name": "Jane Doe" } '
curl -XPOST 'localhost:9200/customer/external/_bulk?pretty' -d '
{"update":{"_id":"1"}}
{"doc": { "name": "John Doe becomes Jane Doe" } }
{"delete":{"_id":"2"}} '
瀏覽你的數據
查詢API
took: es搜索使用了多少毫秒
timed_out 是否超時
_shards 告訴我們多少個分片被搜索,和被成功和失敗搜索的分片的數量
hits 搜索結果
hits.total 結果數量
hits.hits 搜索結果的列表(默認給出前10個)
_score 評分
查詢語句:
Query DSL
{"query":{"match_all":{}}}
規定數目
curl -XPOST 'localhost:9200/bank/_search?pretty'-d '
{ "query": { "match_all": {} }, "size": 1 }'
分頁
curl -XPOST 'localhost:9200/bank/_search?pretty'-d '
{
"query": { "match_all": {} },
"from": 10,
"size": 10
}'
規定返回指定的field
curl -XPOST 'localhost:9200/bank/_search?pretty'-d '
{ "query": { "match_all": {} },
"_source": ["account_number",
"balance"] }'
match:
curl -XPOST 'localhost:9200/bank/_search?pretty'-d '
{ "query":
{ "match":
{ "account_number": 20
}
}
}'
bool: 加入布爾邏輯
curl -XPOST 'localhost:9200/bank/_search?pretty'-d '
{ "query": { "bool": { "must": [ { "match": { "address": "mill" } }, { "match": { "address": "lane" } } ] } } }'
curl -XPOST 'localhost:9200/bank/_search?pretty'-d '
{ "query": { "bool": { "should": [ { "match": { "address": "mill" } }, { "match": { "address": "lane" } } ] } } }'
curl -XPOST 'localhost:9200/bank/_search?pretty'-d '
{ "query": { "bool": { "must": [ { "match": { "age": "40" } } ], "must_not": [ { "match": { "state": "ID" } } ] } } }'
filter
使用filter,es不再計算相關性得分,只是嚴格的按照條件過濾
比如:range
curl -XPOST 'localhost:9200/bank/_search?pretty'-d '
{ "query": { "bool": { "must": { "match_all": {} }, "filter": { "range": { "balance": { "gte": 20000, "lte": 30000 } } } } } }'
Aggregations
提供能力是分組和提煉你的數據 就像sql里面的GROUP BY
es里你可以查詢返回hit和hit的聚合,在一次查詢中
而且可以進行多重聚合
安裝state分類,然后返回10個狀態,按照數量排序
設置size=0,不展示hits,因為我們只關心聚合結果
SELECT state, COUNT(*) FROM bank GROUP BY state ORDER BY COUNT(*) DESC
平局值 聚合每一種balance的平均值
suggest
lasticsearch 0.9.0.3終于基于AnalyzingSuggester加上了prefix suggestions ,可直接做搜索提示功能,在0.9.0.1之前版本都是使用外部插件實現的
參考文章
http://www.nosqldb.cn/1376024289369.html
http://www.cnblogs.com/jiuyuehe/p/3840821.html
總結
es是一個簡單又復雜的產品,還有很多高級的功能。
拓展
官方文檔:
https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html
elasticSearch中文社區:
elasticsearch 索引優化:
http://itindex.net/detail/52316-elasticsearch-%E7%B4%A2%E5%BC%95-%E4%BC%98%E5%8C%96