全文搜尋引擎Elasticsearch6.x 入門
全文搜尋的需求非常大。而開源的解決辦法Elasricsearch(Elastic)就是一個非常好的工具。目前是全文搜尋引擎的首選。
Elastic 的底層是開源的Lucene。Elastic提供了REST API的操作介面。是Lucene的擴充套件。底層依舊是索引,但是可以把大索引切成n片,放到不同的節點,所以就實現了分散式。也就理所當然的是讀寫負載均衡。此外,他還是一個分散式實時文件儲存,其中每個field可被搜尋。 ES 可以自動將海量資料分佈到多臺伺服器上去儲存和檢索海量資料。可以在秒級別在每臺伺服器上分析資料。
下面簡單的介紹一下Elastic並且從零開始搭建一個Elastic。
一、簡介
基本元件: (1).索引(index):文件容器,類似於關係型資料庫中的庫。索引名必須是小寫字母。
(2).型別(type):型別是索引內部的邏輯分割槽。其意義完全取決與使用者需求,一個索引內部可定義多個型別。類似於關係型資料庫中的表結構,欄位。
(3).文件(document):文件是Lucene索引和搜尋的原子單位。它包含多個域。基於JSON格式儲存。每個域的格式類似於字典
(4).對映(mapping):原始內容儲存為文件之前的分析,對映就是定義此對映過程該如何實現。(例如切詞,過濾)
叢集元件:(1)Cluster:ES的叢集標識為叢集名稱。預設為“elasticsearch”,節點靠此名字決定加入到哪一個叢集中。一個節點只能屬於一個叢集。
(2).Node:執行單個ES例項的主機。節點的標識靠節點名。
(3).Shard:將索引切割成為的物理儲存元件,但每一個shared都是一個獨立且完整的索引,建立索引時,ES預設分割為5個shard。使用者也可以按需自定義,建立完成後不可修改。shard有兩種,primary和replica。用於負載均衡。
ES Cluster啟動過程。通過多播(或單播)在9300/tcp查詢同一叢集中的其他節點,並建立通訊。叢集中所有節點會選舉出一個主節點負責管理整個叢集狀態。以及在叢集範圍內決定shared的分佈。
二、安裝
安裝環境 Linux centos7.3 3臺. 直接就安裝成叢集。Elastic 的安裝需要Java環境。不會配置Java環境的請參考
這裡也簡單的演示一下JAVA的環境配置。首先準備好jdk的tar包。下載網頁
# mkdir /usr/java
# tar xf jdk-8u151-linux-i586.tar.gz -C /usr/java
# vim /etc/profile
JAVA_HOME=/usr/java/jdk1.8.0_151
export JRE_HOME=/usr/java/jdk1.8.0_151/jre
export CLASSPATH=.:$JAVA_HOME/lib:$JRE_HOME/lib:$CLASSPATH
export PATH=$JAVA_HOME/bin:$JRE_HOME/bin:$PATH
# update-alternatives --install /usr/bin/java java /usr/java/jdk1.8.0_151/bin/java 300
# update-alternatives --install /usr/bin/javac javac /usr/java/jdk1.8.0_151/bin/javac 300
# update-alternatives --config java
共有 3 個程式提供“java”。
選擇 命令
-----------------------------------------------
*+ 1 /usr/lib/jvm/jre-1.7.0-openjdk.x86_64/bin/java
2 /usr/lib/jvm/jre-1.6.0-openjdk.x86_64/bin/java
3 /usr/java/jdk1.8.0_151/bin/java
按 Enter 來儲存當前選擇[+],或鍵入選擇號碼:3
若出現 -bash: /usr/java/jdk1.8.0_151/bin/java: /lib/ld-linux.so.2: bad ELF interpreter: 沒有那個檔案或目錄 這個錯誤, 則執行 yum install glibc.i686 即可。
至此,安裝成功jdk。下來安裝Elasticsearch。下載頁面
下載好rpm包。執行
# rpm -ivh elasticsearch-6.1.1.rpm
warning: elasticsearch-6.1.1.rpm: Header V4 RSA/SHA512 Signature, key ID d88e42b4: NOKEY
Preparing... ########################################### [100%]
Creating elasticsearch group... OK
Creating elasticsearch user... OK
1:elasticsearch ########################################### [100%]
### NOT starting on installation, please execute the following statements to configure elasticsearch service to start automatically using chkconfig
sudo chkconfig --add elasticsearch
### You can start elasticsearch service by executing
sudo service elasticsearch start
啟動Elasticsearch。
# systemctl start elasticsearch
接下來修改配置檔案。
# vim /etc/elasticsearch/elasticsearch.yml
cluster.name: my-elastic
# 叢集名字,相同叢集名字的節點會放到同一個叢集下
node.name: "node-1"
# 節點名字
discovery.zen.minimum_master_nodes: 2
#指定叢集中的節點中有幾個有master資格的節點。
#對於大叢集可以寫3個以上。
discovery.zen.ping.timeout: 3s
#預設是3s,這是設定叢集中自動發現其它節點時ping連線超時時間
discovery.zen.ping.multicast.enabled: false
#設定是否開啟多播發現節點,預設是true。
network.bind_host: 192.168.40.129
#設定繫結的ip地址,這是我的虛擬機器的IP。
network.publish_host: 192.168.40.129
#設定其它節點和該節點互動的ip地址。
network.host: 0.0.0.0
#同時設定bind_host和publish_host上面兩個引數。
transport.tcp.port: 9300
#設定參與叢集的埠
http.port: 9200
#接收請求埠
#discovery.zen.ping.unicast.hosts:["節點1的 ip","節點2 的ip","節點3的ip"]
#指明叢集中其它可能為master的節點ip,以防es啟動後發現不了叢集中的其他節點。
啟動後,發現9200,9300埠處於監聽狀態。 如果發現,network.host不能繫結到0.0.0.0上。(一啟動就出錯,則可能的原因如下)
接下來給其餘的兩個節點同樣的步驟安裝Elasticsearch。
三、核心概念
首先,elasticsearch 是基於lucene開發,lucene的開發十分複雜,api複雜(需要大量的java程式碼才能完成一個簡單的功能)。 (1) Near RealTime(NRT):近實時。基於es的搜尋在秒級別。 (2) Index (索引):包含一堆相似結構的文件資料。比如客戶索引,商品索引,訂單索引,索引有一個名稱,一個index包含很多個document。(3) Documents (文件): es的最小資料單元。一個document可以是一條客戶資料,一條商品分類資料,一條訂單資料,通常是JSON資料表示,每個index下的type中,都可以去儲存多個document。一個document裡面有多個field。每個field就是一個數據欄位。
{
"id" : "qWAEoJU",
"product_name" : "蒂花之秀",
"product_desc" : "烏黑亮麗",
"category" : "2",
"category_name" : "日化用品"
}
(4) Type (型別):每個索引裡有一個或者多個type。type是index中的一個邏輯資料分類。一個type下的document都有相同的field。
比如商品index。裡面存放了所有的商品資料。商品document。但商品的種類很多。每個種類的document的field可能不太一樣。比如電器商品和生鮮商品。(生鮮商品type,電器商品type,日化商品type) 日化商品type:id ,product_name ,product_desc,category_id,category_name 電器商品type:id ,product_name ,product_desc,category_id,category_name,service_period 生鮮商品type:id ,product_name ,product_desc,category_id,category_name,eat_period
然後每一個type內又有一堆的document。就不舉例了。 (5) Shard:單臺伺服器無法儲存大量的資料,es可以將一個索引中的資料分為多個shard。分佈在很多臺伺服器上,有了shard就實現了橫向擴充套件。儲存更多的資料。讓搜尋和分析操作分佈到多臺伺服器上去執行。
(6) replica:為了防止某一臺伺服器上的shard丟失。因此可以為每個shared建立多個replica副本。多個replica可以提升搜尋操作的吞吐和效能。primary shard(建立索引時一次性建立,預設5個)replica shard(隨時修改,預設一個)。
下圖詳細的介紹了 shard和replica。
四、安裝後相關簡介
通過rpm包安裝之後。會安裝上很多的檔案。除了/etc/elasticsearch 下的配置檔案外,還有很多。# pwd
/usr/share/elasticsearch/bin
# ls
elasticsearch elasticsearch-env elasticsearch-keystore elasticsearch-plugin elasticsearch-translog
這些命令是es的外掛,日誌等管理工具。plugins 是放es相關外掛的。
接下來下載和安裝解壓縮Kibana。使用裡面的開發介面,去操作Elasticsearch。
# yum -y install kibana-6.1.1-x86_64.rpm
安裝完成後、可簡單修改其配置檔案 /etc/kibana/kibana.yml 改變其監聽埠(預設是localhost)。
通過 systemctl start kibana 啟動。而後通過瀏覽器訪問。
之後就可以通過kibana 的dev tool去操作
叢集狀態: green: 每個索引的primary shard和replica shard 都是active狀態 yellow:每個索引的primary shard 都是active 但是 部分索引的replica不是active的 red:有部分索引的primary shard 不是active的。
五、簡單操作
索引操作 (1)、檢視叢集中都有哪些索引。curl -X GET localhost:9200/_cat/indices
(2)、建立索引。
# curl -X PUT localhost:9200/test_index?pretty
{
"acknowledged" : true,
"shards_acknowledged" : true,
"index" : "test_index"
}
(3)、刪除索引。
# curl -X DELETE localhost:9200/test_index?pretty
{
"acknowledged" : true
}
六、入門案例實戰
模擬場景:電商網站。需要基於ES構建的後臺系統。提供以下功能。 (1)、對商品進行CRUD(增刪改查)操作 (2)、執行簡單的結構化查詢 (3)、可以執行全文檢索,以及複雜的phrase(短語)檢索 (4)、對於全文檢索內容可以進行高亮顯示 (5)、對資料進行局和分析 一、新增商品,新增文件,新增索引。PUT /ecommerce/product/1
{
"name" : "xiaomi6",
"desc" : "wei fashao ersheng",
"price" : "2300",
"producer" : "xiaomi keji",
"tags" : ["heikeji","fashao"]
}
PUT /ecommerce/product/2
{
"name" : "iphoneX",
"desc" : "gaoduan daqi",
"price" : "8300",
"producer" : "apple",
"tags" : ["qianwei","shishang"]
}
二、檢索商品。
# curl -XGET localhost:9200/ecommerce/product/1
{"_index":"ecommerce","_type":"product","_id":"1","_version":1,"found":true,"_source":{
"name" : "xiaomi6",
"desc" : "wei fashao ersheng",
"price" : "2300",
"producer" : "xiaomi keji",
"tags" : ["heikeji","fashao"]
}
三、修改,替換商品
可以直接替換,也可以修改。
POST /ecommerce/product/1/_update
{
"doc":{
"price": "2400"
}
}
四、刪除商品
DELETE /ecommerce/product/1
高階操作
搜尋所有的商品。GET ecommerce/product/_search
查詢結果:
took: 消耗了幾毫秒。
timed_out:是否超時
_shards:資料拆分成了5個分片。所以對於搜尋請求。會打到所有的primary shard 或 replica shard
hits.total:查詢結果的數量。2個
hits.max_score:score的含義,就是document對於一個search相關度的分配分數。越相關,就越匹配。
{
"took": 90,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 2,
"max_score": 1,
"hits": [
{
"_index": "ecommerce",
"_type": "product",
"_id": "2",
"_score": 1,
"_source": {
"name": "iphoneX",
"desc": "gaoduan daqi",
"price": "8300",
"producer": "apple",
"tags": [
"qianwei",
"shishang"
]
}
},
{
"_index": "ecommerce",
"_type": "product",
"_id": "1",
"_score": 1,
"_source": {
"name": "xiaomi6",
"desc": "wei fashao ersheng",
"price": "2400",
"producer": "xiaomi keji",
"tags": [
"heikeji",
"fashao"
]
}
}
]
}
}
查詢名字裡帶 xiaomi 的商品。
GET /ecommerce/product/_search?q=name:xiaomi
GET /ecommerce/product/_search
{
"query" : {
"match" : {
"name" :"xiaomi"
}
}
}
分頁查詢商品,總共3條商品。假設每頁就顯示一條。現在顯示第2頁。
GET ecommerce/product/_search
{
"query":{
"match_all": {}},
"from":1,
"size":1
}
只查出名稱和價格
GET ecommerce/product/_search
{
"query":{
"match_all": {}
},
"_source": ["name","price"]
}
查出商品包含xiaomi且價格大於2000元的。
GET ecommerce/product/_search
{
"query":{
"bool":{
"must":{
"match":{
"name":"xiaomi"
}
},
"filter":{
"range":{
"price":{
"gt": 2000
}
}
}
}
}
}
短語搜尋,與全文搜尋相對應。短語搜尋是必須匹配。
GET ecommerce/product/_search
{
"query":{
"match_phrase":{
"producer": "keji"
}
}
}
搜尋高亮顯示。
GET ecommerce/product/_search
{
"query":{
"match":{
"producer": "keji"
}
},
"highlight": {
"fields": {
"producer": {}
}
}
}
更多詳細的查詢語法或其他內容
Options :History :Feedback :Donate | Close |