ElasticSearch學習文件2018.11
1 Elasticsearch安裝
1.1 ES6.0版本安裝head外掛
1.1 下載head外掛
下載地址:https://github.com/mobz/elasticsearch-head;點選clone or download按鈕
1.2 安裝node.js
下載地址:https://nodejs.org/en/download/
1.3 安裝grunt
執行head需要藉助grunt命令 ,但是安裝grunt需要藉助npm
進入nodejs安裝根目錄,輸入以下命令安裝grunt
npm install -g grunt -cli
1.4 安裝pathomjs
進入head根目錄,輸入npm install命令
1.5 執行head
在head根目錄下執行grunt server,出現如圖所示內容則啟動成功!
1.6 修改配置檔案
開啟 elasticsearch安裝目錄/config/elasticsearch.yml
在配置檔案末尾加上以下兩句
http.cors.enabled: true http.cors.allow-origin: "*"
修改完成後儲存重啟elasticsearch,然後在head根目錄下鍵入命令grunt server,出現1.5圖示則在瀏覽器位址列訪問http://localhost:9100
出現下圖所示內容表示head外掛安裝成功。
1.2 ElasticSearch6.x版本安裝kibana外掛
2.1 下載地址 : https://www.elastic.co/downloads/kibana
1.7 進入到下載目錄,解壓kibana-6.1.1-windows-x86_64.zip
1.8 進入config編輯kibana.yml,修改kibana的監聽埠和kibana檢視elasticsearch地址
# Kibana is served by a back end server. This setting specifies the port to use. server.port: 5601 # The URL of the Elasticsearch instance to use for all your queries. elasticsearch.url: "http://localhost:9200"
2.4進入bin目錄下雙擊kibana.bat,啟動kibana
預設情況下 http://localhost:5601/ 即可訪問kibana主頁,若elasticsearch連線正常即可看到如下介面表示安裝成功。
1.3 Elasticsearch安裝ik分詞外掛
下載地址:
https://github.com/medcl/elasticsearch-analysis-ik/
解壓zip檔案複製到plugin目錄下即可
使用ik分詞器與使用標準分詞器進行對比
(1)使用standard分詞器,對中文分詞效果不佳
分詞效果
(2)使用ik_smart分詞器
分詞結果
(3)使用ik_max_word分詞器
1.4 ElasticSearch基本概念
分片:Elasticsearch索引是由一個或多個分片組成的,每個分片包含了文件集的一部分。
副本:分片的副本
區別:生成索引後,分片的數量可以新增刪除,而分片的數量無法改變。此時修改分片數量
的唯一途徑就是建立另一個索引並重新索引資料。
1.修改索引的自動建立
修改配置檔案elasticsearch.yml 設定action.auto_create_index: false
2.型別確定機制
解決方案是在對映定義檔案中把
numeric_detection 屬性設定為 true ,以開啟更積極的文字檢測
3.禁用欄位猜測型別
要關閉自動新增欄位,可以把dynamic屬性設定為false
4.Elasticsearch 核心型別
①string:字串;
②number:數字
③date:日期
④boolean:布林型別
⑤binary:二進位制(二進位制欄位是儲存在索引中的二進位制資料的Base64表示,可用來儲存以二進位制形式正常寫入
的資料,例如影象)
5.公共屬性
①index_name:定義儲存在索引中的欄位名稱,預設物件名
②index:是否索引,預設(analyzed),設定為no則不索引,字串可以設定not_analyzed,
則不分析直接編入索引,此時檢索時需要全部匹配
③store:是否寫入索引,預設為no(如果使用了_source欄位,沒有編入也可返回該值),設定yes
可用於搜尋
④boost:預設值為1,設定權重,值越大,欄位中值的重要性頁越高
⑤null_value:如果該欄位並非索引文件的一部分,此屬性指定應寫入索引的值
預設的行為是忽略該欄位。(這tm怎麼理解?)
⑥copy_to :此屬性指定一個欄位,欄位的所有值都將複製到該指定欄位
⑦include_in_all:此屬性指定該欄位是否應包括在 _all 欄位中。預設情況下,如果使
用 _all 欄位,所有欄位都會包括在其中
注意:模糊查詢(like)不能使用索引,查詢效率低
1.5 MySQL和Elasticsearch對比
springboot與elasticsearch版本對應關係
1.6 ElasticSearch叢集搭建
ElasticSearch橫向擴充套件能力很強,叢集就是單機版的複製,
複製多個elasticsearch,這裡配置一主二僕,修改config目錄下elasticsearch.yml檔案
① slave配置如下:
http.cors.enabled: true http.cors.allow-origin: "*" #master的配置資訊: #叢集名稱,保證唯一 cluster.name: elasticsearch #節點名稱,必須不一樣 node.name: slave2 #當前節點不作為叢集協調者,但儲存資料 node.master: false node.data: true #必須為本機的ip地址 network.host: 127.0.0.1 #服務埠號,在同一機器下必須不一樣 http.port: 9202 #叢集間通訊埠號,在同一機器下必須不一樣 transport.tcp.port: 9302 #設定叢集自動發現機器ip集合 discovery.zen.ping.unicast.hosts: ["127.0.0.1:9300", "127.0.0.1:9301", "127.0.0.1:9302"]
②master配置如下:
http.cors.enabled: true http.cors.allow-origin: "*" #master的配置資訊: #叢集名稱,保證唯一 cluster.name: elasticsearch #節點名稱,必須不一樣 node.name: master #當前節點作為叢集協調者且儲存資料 node.master: true node.data: true #必須為本機的ip地址 network.host: 127.0.0.1 #服務埠號,在同一機器下必須不一樣 http.port: 9200 #叢集間通訊埠號,在同一機器下必須不一樣 transport.tcp.port: 9300 #設定叢集自動發現機器ip集合 discovery.zen.ping.unicast.hosts: ["127.0.0.1:9300", "127.0.0.1:9301", "127.0.0.1:9302"]
配置完成後,啟動三個節點,在head外掛下會看到如圖所示的效果:
1.7 linux下elasticsearch安裝問題
[1]: max file descriptors [4096] for elasticsearch process is too low, increase to at least [65536]
解決:切換到root使用者,編輯limits.conf 新增類似如下內容
vi /etc/security/limits.conf
新增如下內容:
* soft nofile 65536 * hard nofile 131072 * soft nproc 2048 * hard nproc 4096
[2]: max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]
解決:切換到root使用者修改配置sysctl.conf
vi /etc/sysctl.conf
新增下面配置:
vm.max_map_count=655360
並執行命令:
sysctl –p
[3]: system call filters failed to install; check the logs and fix your configuration or disable system call filters at your own risk
其他錯誤:
https://blog.csdn.net/qq_33363618/article/details/78882827
2 Elasticsearch查詢
2.1 Elasticsearch Restful API
①新增記錄
向指定的 /Index/Type 傳送 PUT 請求,就可以在 Index 裡面新增一條記錄
http://localhost:9200/cmbc/employee
{ "first_name": "zkr-yanghuiying", "last_name": "pacbj-yanghuiying", "age": 24, "about": "I love to coding ...", "interests": [ "games" ], "join_time": "2018-03-06" }
注意: /Index/Type後面可以加id,id可以為數字或者字串,不加會自動生成,此時請求為PUT請求。新增記錄的時候,也可以不指定 Id,這時要改成 POST 請求
② 檢視記錄
向/Index/Type/Id發出 GET 請求,就可以檢視這條記錄。
③ 刪除記錄
刪除記錄就是Delete請求
Delete http://localhost:9200/cmbc/employee
刪除文件加Id即可,刪除索引則加Index即可
④ 更新記錄(有點糊塗,後期再研究)
ES可以使用POST或者PUT進行全部更新,如果指定ID的文件已經存在,則執行更新操作。
注意:es執行更新操作的時候,ES首先將舊的文件標記為刪除狀態,然後新增新的文件,舊的文件不會立即消失,但是你也無法訪問,ES會在你繼續新增更多資料的時候在後臺清理已經標記為刪除狀態的文件。
區域性更新,可以新增新欄位或者更新已有欄位(必須使用POST)
http://localhost:9200/cmbc/employee/TuAQIGQBNnQMC6EoMDSM/_update
{ "doc": { "age": 25, "last_name": "zkr-lijunkai" } }
區別: 全部更新,是直接把之前的老資料,標記為刪除狀態,然後,再新增一條更新的;局域更新,只是修改某個欄位。
⑤ 查詢
5.1 返回所有記錄,使用 GET 方法,直接請求/Index/Type/_search,就會返回所有記錄
http://localhost:9200/_search
http://localhost:9200/cmbc/employee/_search
{ "took": 15, "timed_out": false, "_shards": { "total": 5, "successful": 5, "skipped": 0, "failed": 0 }, "hits": { "total": 13, "max_score": 1, "hits": [ { "_index": "cmbc", "_type": "employee", "_id": "dR_7G2QBVx78n1CFS4kg", "_score": 1, "_source": { "first_name": "zkr-liuyang", "last_name": "pacbj-liuyang", "age": 22, "about": "I love to coding ...", "interests": [ "games" ], "join_time": "2018-03-06" } }, { "_index": "cmbc", "_type": "employee", "_id": "eB_8G2QBVx78n1CFVol2", "_score": 1, "_source": { "first_name": "zkr-yanghuiying", "last_name": "pacbj-yanghuiying", "age": 24, "about": "I love to coding ...", "interests": [ "games" ], "join_time": "2018-03-06" } } ] } }
返回結果的 took欄位表示該操作的耗時(單位為毫秒),timed_out欄位表示是否超時,hits欄位表示命中的記錄
5.2 Match查詢,指定匹配條件
POST http://localhost:9200/cmbc/employee/_search
{ "query": { "match": { "first_name": "zkr-liuyang" } } }
網上的教程使用的是get請求拼json查詢條件,但是post請求傳送json資料也是可以的。
我們可以通過size欄位,指定返回幾條結果
"_score": 0.87546873 _score表示得分(匹配程度),查詢出來的結果會按照匹配程度的大小倒排。
還可以通過from欄位,指定位移。
"from": 1(從位置1開始(預設是從位置0開始))
5.3 查詢所有
{ "query": { "match_all": {} } }
ElasticSearch中Filter和Query的異同
如下例子,查詢性別是女,所在的州是PA,過濾條件是年齡是39歲,balance大於等於10000的文件:
{ "query": { "bool": { "filter": [ {"term": {"age": "39"}}, {"range": {"balance": {"gte": "10000"}} } ], "must": [ {"match":{"gender": "F"}}, {"match": {"state": "PA"}} ] } } }
2.2 Query與Filter異同:
Query查詢上下文:
在查詢上下文中,查詢會回答這個問題——“這個文件匹不匹配這個查詢,它的相關度高麼?” ES中索引的資料都會儲存一個_score分值,分值越高就代表越匹配。另外關於某個搜尋的分值計算還是很複雜的,因此也需要一定的時間。查詢上下文 是在 使用query進行查詢時的執行環境,比如使用search的時候。
Filter過濾器上下文:
在過濾器上下文中,查詢會回答這個問題——“這個文件匹不匹配?”
答案很簡單,是或者不是。它不會去計算任何分值,也不會關心返回的排序問題,因此效率會高一點。
過濾上下文 是在使用filter引數時候的執行環境,比如在bool查詢中使用Must_not或者filter。另外,經常使用過濾器,ES會自動的快取過濾器的內容,這對於查詢來說,會提高很多效能。
總結
查詢上下文中,查詢操作不僅僅會進行查詢,還會計算分值,用於確定相關度;在過濾器上下文中,查詢操作僅判斷是否滿足查詢條件,且查詢的結果可以被快取。
注意:此處JestClient是單例的,在多執行緒併發訪問時注意加鎖同步或者使用非同步執行jestClient.executeAsync()或者自定義JestClientFactory設定HttpClientConfig的多執行緒屬性為true,從而重新構造JestClient。
2.3 Elasticsearch模糊查詢
Elasticsearch模糊查詢
GET /_search { "query": { "wildcard" : { "user" : "ki*y" } } }
也可以使用下面這種查詢方式
GET /_search { "query": { "wildcard" : { "user" : { "value" : "ki*y", "boost" : 2.0 } } } }
wildcard query應杜絕使用萬用字元打頭,實在不得已要這麼做,就一定需要限制使用者輸入的字串長度。 最好換一種實現方式,通過在index time做文章,選用合適的分詞器,比如nGram tokenizer預處理資料,然後使用更廉價的term query來實現同等的模糊搜尋功能。 對於部分輸入即提示的應用場景,可以考慮優先使用completion suggester, phrase/term suggeter一類效能更好,模糊程度略差的方式查詢,待suggester沒有匹配結果的時候,再fall back到更模糊但效能較差的wildcard, regex, fuzzy一類的查詢。
2.4 物件巢狀查詢(Nested dataype)
參考連結 : https://www.elastic.co/guide/en/elasticsearch/reference/current/nested.html
參考連結 : https://www.elastic.co/guide/cn/elasticsearch/guide/current/nested-query.html
巢狀型別是物件資料型別的專門化版本,它允許物件陣列以一種彼此獨立查詢的方式被索引。
內部物件欄位的陣列並不像您預期的那樣工作。Lucene沒有內部物件的概念,因此,ElasticSearch將物件層次結構變平為一個簡單的欄位名和值列表。例如,下面的文件
PUT my_index/_doc/1
{ "group": "fans", "user": [ { "first": "John", "last": "Smith" }, { "first": "Alice", "last": "White" } ] }
使用者欄位被動態地新增為一類物件欄位
將會在內部被轉換成一個更像這樣的文件:
{ "group": "fans", "user.first": [ "alice", "john" ], "user.last": [ "smith", "white" ] }
User。User.first,user.last欄位被平鋪到多值欄位中,而alice和white之間的關聯丟失了。該文件將錯誤地匹配alice和smith的查詢
如果您需要索引物件陣列並維護陣列中每個物件的獨立性,您應該使用巢狀資料型別,而不是物件資料型別。在內部,巢狀物件將陣列中的每個物件作為單獨的隱藏文件進行索引,這意味著每個巢狀的物件都可以獨立地查詢,並使用巢狀查詢:
PUT my_index
{ "mappings": { "_doc": { "properties": { "user": { "type": "nested" } } } } }
PUT my_index/_doc/1
{ "group": "fans", "user": [ { "first": "John", "last": "Smith" }, { "first": "Alice", "last": "White" } ] }
GET my_index/_search
{ "query": { "nested": { "path": "user", "query": { "bool": { "must": [ { "match": { "user.first": "Alice" }}, { "match": { "user.last": "Smith" }} ] } } } } }
GET my_index/_search
{ "query": { "nested": { "path":"user", "query":{ "bool":{ "must":[ {"match":{"user.first":"Alice"}}, {"match":{"user.last":"White"}} ] } }, "inner_hits":{ "highlight":{ "fields":{ "user.first": {} } } } } } }
GET /my_index/blogpost/_search
{ "query": { "bool": { "must": [ {"match": {"title": "eggs" }}, {"nested": { "path": "comments", "query": { "bool": { "must": [ {"match":{"comments.name": "john"}}, {"match": {"comments.age": 28}} ] } } } } ] }}}
未完待續...