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}} ] } } } } ] }}}
未完待續...
