前言
前端時間利用ES開發一個"附近地理位置+其它資訊"查詢搜尋的功能(據了解,Redis和PostgreSQL也能實作同樣的功能),實踐中遇到了不少的問題,是以通過這篇文章記錄下踩填坑過程。
es with docker
個人喜好,一般使用中間件都喜歡用Docker運作較新版本的,用
docker pull elasticsearch
指令拉下來的版本一般不會是最新的,是以可以從
這裡找到最新版本的拉取指令,稍加改造後我需要的是這樣的:
docker run --name elasticsearch -e "ES_JAVA_OPTS=-Xms256m -Xmx256m" -d -p 9200:9200 -p 9300:9300 docker.elastic.co/elasticsearch/elasticsearch-oss:6.3.2
注意到這裡指定的鏡像是
elasticsearch-oss:6.3.2
,這個
-oss
表示不包括
X-Pack
的ES鏡像,這也是在6.0+版本後劃分的,剩下兩種類型是
basic
(預設)和
platinum
,具體官方說明可以看下圖。
Elasticsearch Docker Image Types
如果啟動失敗,使用指令
docker logs elasticsearch
檢視日志即可,
-f
參數用于監聽,其中一種啟動錯誤是要求你修改
vm.max_map_count
這個系統環境參數,Linux可參考指令
sysctl -w vm.max_map_count=262144
設定即可(其它系統在文末官方參考連結中有更詳細介紹)。
create mapping
這部分是重點,之前遇到的坑就是type mapping這塊。
- "_id is not configurable"
es2.0+版本中,
_id
是可以配置的,網上也有一堆告訴你怎麼設定,但es6.3.2中建立mapping并指定
_id
配置的時候,es傳回錯誤中就出現了上面那句,在社群可以找到了這個
Discuss。高版本中的
_id
是不能配置了,一般來說,在添加Document的時候,如果隻指定Index和Document Type,那麼es會随機給這個
_id
配置設定一個值,但如果添加的時候指定這個
_id
值,那麼ES就不會再随機配置設定這個值。不過注意,即使你指定的
_id
是一個數值,但在實際儲存和傳回中都是字元串類型;
- "Mapping with Index not_analyzed is not working"
這個問題在Github上也有相關的
Issues,我在這裡先還原下當初建立mapping的配置:
{
"properties": {
# 當初的想法是指定shopId這個字段不要分析,然後keyword字段要進行分析
"shopId": {
"type": "integer",
"index": "not_analyzed"
},
"location": {
"type": "geo_point"
},
"keyword":{
"type": "text",
"index": "analyzed",
"analyzer": "ik_max_word"
}
}
}
建立完上述mapping後通路
http://localhost:9200/{index}/{type}/_mapping
,但傳回結果(如下)和上面指定的mapping并不相同:
{
"{index}": {
"mappings": {
"{type}": {
"properties": {
"shopId": {
"type": "integer"
},
"location": {
"type": "geo_point"
},
"keyword": {
"type": "text",
"analyzer": "ik_max_word"
},
}
}
}
}
}
之後還是在官方文檔中找到答案,發現确實有兩點值得記錄一下。
- 第一點:es5.0之後,為字元串新增了
類型,而之前的版本中隻有keyword
類型,通過index屬性判斷是否需要分詞(預設分詞)。es5.0之後使用keyword type代替index這個屬性,是以指定text
就是分詞,指定"type": "text"
就是不分詞;"type": "keyword"
- 第二點:不需要為type為數字類型integer、long,日期類型date、布爾類型boolean等指定
屬性(而且在高版本es中這也是錯誤的文法,index隻能指定為"index": "not_analyzed"
,false意味着不可查詢),因為這些類型就是不分詞的,如果要分詞請修改為text類型。"index": true | false
ik analysis
IK是國内用得比較多的中文分詞器,與ES安裝內建也比較簡單,首先進入docker
docker exec -it elasticsearch bash
,然後用指令
./bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v6.3.2/elasticsearch-analysis-ik-6.3.2.zip
安裝即可(需對應es版本),安裝完使用
docker restart elasticsearch
重新開機服務即可。IK支援兩種分詞方式,
ik_smart
和
ik_max_word
,前者分詞粒度沒有後者細,可以針對實際情況進行選擇。
head plugin
elasticsearch-head插件也是測試的時候用得比較多的插件,以前用ES2的時候是借助plugin腳本安裝的,但這種方式在ES5.0之後被廢棄了,然後作者也推薦了好幾種方式,可以借助npm運作該服務,或者用docker運作服務,不過為了簡單起見我最後選的是
Chrome extension這種方式。
參考連結
Install Elasticsearch with Docker Mapping Text datatype Keyword datatype how-to-not-analyze-in-elasticsearch elasticsearch-analysis-ik elasticsearch-head