簡介
什麼是elasticsearch?
elasticsearch是開源的分佈式、Restfull 風格的數據搜索與分析引擎,是時下最流行的全文搜索引擎。
elasticsearch和Apache Lucene
Apache Lucene是時下最先進、高性能、全功能的搜索引擎庫,Apache Lucene原理和實現複雜。elasticsearch就是爲了解決Lucene複雜性的,elasticsearch基於Lucene,使用java語言開發,對Lucene做了一層封裝,提供一套簡單一致的Restfull 風格API,是的全文檢索更簡單。
elasticsearch不僅僅是全文搜索引擎:
- 一個分佈式實時文檔存儲,每個字段都可以被索引和搜索。
- 一個分佈式實時分析搜索引擎。
- 支持上百個服務節點擴展,支持PB級的結構化數據和非結構化數據。
安裝運行
Windows下安裝
step1 安裝Kibana 下載Elasticsearch 6.2.2的zip包,並解壓到指定目錄,下載地址:https://www.elastic.co/cn/downloads/past-releases/elasticsearch-6-2-2
step2 安裝中文分詞插件,在elasticsearch-6.2.2\bin目錄下執行以下命令
elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v6.2.2/elasticsearch-analysis-ik-6.2.2.zip
step3 啓動es 運行es安裝目錄/bin/elasticsearch.bat
step4 安裝Kibana 下載Kibana,作爲訪問Elasticsearch的客戶端,請下載6.2.2版本的zip包,並解壓到指定目錄,下載地址:https://artifacts.elastic.co/downloads/kibana/kibana-6.2.2-windows-x86_64.zip
step5 啓動Kibana 運行Kibana/bin/kibana.bat
linux下安裝
step1 下載elasticsearch 6.4.0的docker鏡像;
docker pull elasticsearch:6.4.0
step2 修改虛擬內存區域大小,否則會因爲過小而無法啓動;
sysctl -w vm.max_map_count=262144
step3 修改該目錄的權限,使es有權訪問目錄
chmod 777 /mydata/elasticsearch/data/
step4 使用docker命令啓動;
docker run -p 9200:9200 -p 9300:9300 --name elasticsearch \
-e "discovery.type=single-node" \
-e "cluster.name=elasticsearch" \
-v /mydata/elasticsearch/plugins:/usr/share/elasticsearch/plugins \
-v /mydata/elasticsearch/data:/usr/share/elasticsearch/data \
-d elasticsearch:6.4.0
step5 安裝中文分詞器IKAnalyzer,並重新啓動;
docker exec -it elasticsearch /bin/bash
#此命令需要在容器中運行
#進入ES目錄
docker exec -it elasticsearch /bin/bash
elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v6.4.0/elasticsearch-analysis-ik-6.4.0.zip
docker restart elasticsearch
step6 訪問es測試安裝是否成功
http://linux服務器:9200/
step7 下載kibana 6.4.0的docker鏡像
step8 docker命令啓動
docker run --name kibana -p 5601:5601 \
--link elasticsearch:es \
-e "elasticsearch.hosts=http://es:9200" \
-d kibana:6.4.0
step8 訪問測試安裝是否成功
http://linux服務器地址:5601
Kibana是es可視化用戶界面,在DevTol下可以使用es DSL語言操縱ES。
elasticsearch基本概念
全文搜索(Full-Text Search):計算機檢索程序通過掃描文章每一個詞,對每一個詞建立索引,指明該詞在文章中出現次數和位置。當用戶查詢時,檢索程序根據事先建立的索引進行查詢並返回查詢結果給用戶的查詢方式。
倒排索引(Inverted Index):
- 該索引表中每一項都包括一個屬性值和具有該屬性值的各記錄的地址;
- 該索引表不是由記錄確認屬性值,而是由屬性值來確定記錄的位置,因此成爲倒排索引;
- elasticsearch能夠實現高效、快速搜索功能,正是基於倒排索引。
節點 &集羣(Node & Cluster):elasticsearch本質是分佈式數據庫,允許多臺服務器共同工作。每臺服務器可以運行多個es實例,單個實例就是節點(Node),一組節點構成集羣(Cluster)。
索引(Index):elasticsearch管理數據的頂層單位,Index必須小寫英文命名。Index相當於關係數據庫中的數據庫。
文檔(Document):Index中的單條記錄稱爲Document,Document使用JSON格式表示。同一個Index下Document不要求具有相同數據結構(Scheme),但是最好保持一致,這樣可以提供搜索效率。
類型(Type):
- Document可以分組,比如Order這個Index,可以按訂單狀態分組,可以按訂單類型分組,這個分組稱爲Type。
- elasticsearch Tyoe是虛擬邏輯分組,用來過濾Document,Type相當於關係數據庫中的數據表;
- 一個Index下不同Type應該有相似結構,完全不同數據結構的數據應該建立不同Index。
文檔元數據:文檔元數據可以分爲三部分
- _index: 文檔存放位置
- -Type: 文檔類型
- _id: 文檔唯一標識
三者可以唯一表示一個文檔。
字段:Document是一個JSON數據結構,包含許多字段,每個字段都有對應值。字段相當於關係數據庫中的字段。
es和關係數據庫類比圖
elasticsearch入門
elasticsearch交互方式
elasticsearch提供Java API 和 Restfull API。基於Restfull API 其他語言程序可以通過9200端口和es進行通訊。
elasticsearch 請求分析
部件 | 說明 |
VERB | 適當的HTTP方法或謂詞:GET\PUT\DELETE\POST\HEAD。 |
PROTOCOL | http或https(如果elasticsearch前面啓用了代理) |
HOST | elasticsearch集羣中任一節點主機名或者用localhost代表本地節點 |
PORT | elasticsearch端口號,默認9200 |
PATH | API終端路徑(如_count將返回集羣中文檔數量)。PATH可能包含多個組件,例如:_cluster/stats 和 _nodes/stats/jvm |
QUERY_STRING | 任意可選的查詢字符串參數,例如:?pretty 將格式化地輸出 JSON 返回值,使其更容易閱讀 |
BODY | 一個JSON格式請求體 |
HTTP方法說明
HTTP方法 | 說明 |
GET | 獲取請求對象當前狀態 |
PUT | 創建一個對象 |
POST | 改變當前對象狀態 |
DELETE | 刪除一個對象 |
HEAD | 獲取對象的基礎信息 |
基礎命令詳解
查看集羣健康狀態:
GET /_cat/health?v
查看節點狀態:
GET /_cat/nodes?v
查看所有索引信息:
GET /_cat/indices?v
創建索引並查看;
PUT /customer
GET /_cat/indices?v
刪除索引並查看:
DELETE /customer
GET /_cat/indices?v
查看文檔的類型:
GET /pms/_mapping
在索引中添加文檔
PUT /customer/doc/1
{
"name": "John Doe"
}
查看索引中的文檔
GET /customer/doc/1
{
"_index": "customer",
"_type": "doc",
"_id": "1",
"_version": 1,
"found": true,
"_source": {
"name": "John Doe"
}
}
修改索引中的文檔:
POST /customer/doc/1/_update
{
"doc": { "name": "Jane Doe" }
}
{
"_index": "customer",
"_type": "doc",
"_id": "1",
"_version": 2,
"result": "updated",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 1,
"_primary_term": 1
}
GET /customer/doc/1
{
"_index": "customer",
"_type": "doc",
"_id": "1",
"_version": 2,
"found": true,
"_source": {
"name": "Jane Doe"
}
}
刪除索引中文檔:
DELETE /customer/doc/1
對索引文檔進行批量操作
POST /customer/doc/_bulk
{"index":{"_id":"1"}}
{"name": "John Doe" }
{"index":{"_id":"2"}}
{"name": "Jane Doe" }
數據搜索
elasticsearch提供了豐富靈活的查詢語言-查詢表達式(Query DSL),支持構建更加複雜和健壯的查詢。
最簡單的搜索,使用match_all
來表示,例如搜索全部:
GET /pms/_search
{
"query": { "match_all": {} }
}
分頁搜索,from
表示偏移量,從0開始,size
表示每頁顯示的數量;
GET /pms/_search
{
"query": { "match_all": {} },
"from": 0,
"size": 3
}
搜索排序,使用sort
表示,例如按price
字段降序排列;
GET /pms/_search
{
"query": { "match_all": {} },
"sort": { "price": { "order": "desc" } }
}
搜索並返回指定字段內容,使用_source
表示,例如只返回name
和price
兩個字段內容:
GET /pms/_search
{
"query": { "match_all": {} },
"_source": ["name", "price"]
}
條件搜索,使用match
表示匹配條件,例如搜索出price
爲98
的文檔:
GET /pms/_search
{
"query": {
"match": {
"price": 98
}
}
}
文本類型字段的條件搜索,例如搜索address
字段中包含mill
的文檔,對比上一條搜索可以發現,對於數值類型match
操作使用的是精確匹配,對於文本類型使用的是模糊匹配:
GET /pms/_search
{
"query": {
"match": {
"name": "海瀾之家"
}
},
"_source": [
"name",
"subTitle"
]
}
{
"took": 7,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 3,
"max_score": 4.2882357,
"hits": [
{
"_index": "pms",
"_type": "product",
"_id": "30",
"_score": 4.2882357,
"_source": {
"subTitle": "2018夏季新品微彈舒適新款短T男生 6月6日-6月20日,滿300減30,參與互動贏百元禮券,立即分享贏大獎",
"name": "HLA海瀾之家簡約動物印花短袖T恤"
}
},
{
"_index": "pms",
"_type": "product",
"_id": "32",
"_score": 4.2882357,
"_source": {
"subTitle": "HLA海瀾之家短袖T恤男基礎款簡約圓領HNTBJ2E153A藏青(F3)175/92A(50)",
"name": "HLA海瀾之家短袖T恤男基礎款"
}
},
{
"_index": "pms",
"_type": "product",
"_id": "31",
"_score": 3.8090763,
"_source": {
"subTitle": "2018夏季新品短袖T恤男HNTBJ2E080A 藍灰花紋80 175/92A/L80A 藍灰花紋80 175/92A/L",
"name": "HLA海瀾之家藍灰花紋圓領針織布短袖T恤"
}
}
]
}
}
組合搜索
組合搜索,使用bool
來進行組合,must
表示同時滿足,例如搜索subTitle
字段中同時包含2018
和男生
的文檔;
GET /pms/_search
{
"query": {
"bool": {
"must": [
{ "match": { "subTitle": "2018" } },
{ "match": { "subTitle": "男生" } }
]
}
}
}
組合搜索,should
表示滿足其中任意一個,搜索name
字段中包含HLA
或者海瀾之家的文檔
GET /pms/_search
{
"query": {
"bool": {
"should": [
{ "match": { "name": "HLA" } },
{ "match": { "name": "海瀾之家" } }
]
}
}
}
組合搜索,must_not表示不同時滿足,搜索subTitle字段不同時包含移動 電信的文檔
GET /pms/_search
{
"query": {
"bool": {
"must_not": [
{ "match": { "subTitle": "移動" } },
{ "match": { "subTitle": "電信" } }
]
}
}
}
組合搜索,must和must_not配合,搜索name包含小米subTitle不包含電信的文檔
GET /pms/_search
{
"query": {
"bool": {
"must": [
{ "match": { "name": "小米" } }
],
"must_not": [
{ "match": { "subTitle": "電信" } }
]
}
}
}
過濾搜索
使用filter來表示,比如獲取price在600-1000之間的商品
GET /pms/_search
{
"query": {
"bool": {
"must": { "match_all": {} },
"filter": {
"range": {
"price": {
"gte": 600,
"lte": 1000
}
}
}
}
}
}
搜索聚合
對搜索結果進行聚合,用aggs表示,類似sql的group by 。例如對brandName進行聚合,統計出brandName相同的數目
GET /pms/_search
{
"size": 0,
"aggs": {
"group_by_brandName": {
"terms": {
"field": "brandName"
}
}
}
}
{
"took": 90,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 11,
"max_score": 0,
"hits": []
},
"aggregations": {
"group_by_brandName": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "小米",
"doc_count": 4
},
{
"key": "海瀾之家",
"doc_count": 3
},
{
"key": "NIKE",
"doc_count": 2
},
{
"key": "華爲",
"doc_count": 1
},
{
"key": "蘋果",
"doc_count": 1
}
]
}
}
}
嵌套聚合,同時聚合brandName和price,計算出brandName相同的數目和price的平均值
GET /pms/_search
{
"size": 0,
"aggs": {
"group_by_brandName": {
"terms": {
"field": "brandName"
},
"aggs": {
"average_price": {
"avg": {
"field": "price"
}
}
}
}
}
}
{
"took": 123,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 11,
"max_score": 0,
"hits": []
},
"aggregations": {
"group_by_brandName": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "小米",
"doc_count": 4,
"average_price": {
"value": 2461.5
}
},
{
"key": "海瀾之家",
"doc_count": 3,
"average_price": {
"value": 88
}
},
{
"key": "NIKE",
"doc_count": 2,
"average_price": {
"value": 434
}
},
{
"key": "華爲",
"doc_count": 1,
"average_price": {
"value": 3788
}
},
{
"key": "蘋果",
"doc_count": 1,
"average_price": {
"value": 5499
}
}
]
}
}
}
對聚合搜索的結果進行排序
GET /pms/_search
{
"size": 0,
"aggs": {
"group_by_brandName": {
"terms": {
"field": "brandName",
"order": {
"average_price": "desc"
}
},
"aggs": {
"average_price": {
"avg": {
"field": "price"
}
}
}
}
}
}
{
"took": 39,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 11,
"max_score": 0,
"hits": []
},
"aggregations": {
"group_by_brandName": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "蘋果",
"doc_count": 1,
"average_price": {
"value": 5499
}
},
{
"key": "華爲",
"doc_count": 1,
"average_price": {
"value": 3788
}
},
{
"key": "小米",
"doc_count": 4,
"average_price": {
"value": 2461.5
}
},
{
"key": "NIKE",
"doc_count": 2,
"average_price": {
"value": 434
}
},
{
"key": "海瀾之家",
"doc_count": 3,
"average_price": {
"value": 88
}
}
]
}
}
}