概述
Elasticsearch是一個基於Lucene的搜索服務器。以下簡稱ES,版本爲2.3左右的。
ES的版本比較多,目前已經到了5.3版本,但是很多公司都沒有使用最新版本,我所在的公司也是如此。在沒有接觸ES之前,我不知道這個全文索引的框架,加上我英文不好,學習的時候真的給我帶了不少的問題,踩了很多的坑。下面,我將從一個0基礎的角度來介紹我學習ES的過程。感謝我的指導老師騫哥、祥哥。
一、如何學習ES
ES的中文文檔並不多,在加上ES的版本很多,給翻譯帶來了很大的工作量。但是,我在學習過程中找到了一些文檔和資料,可以快速的讓你瞭解ES是什麼,該怎麼使用。
1.ES官方文檔
https://www.elastic.co/guide/en/elasticsearch/reference/current/search-search.html
學習ES的官方文檔中的Getting Started,可以讓你對ES的概念有個大概的瞭解,包括ES的一些基本概念,ES的安裝,索引,查詢等方面的知識。但是對於英文不好的人來說,要理解這些概可能就需要看上個一兩天,都還不一定能懂。那麼請看條例2。
2.Getting Started的中文博客地址
http://blog.csdn.net/cnweike/article/details/33736429
這篇博客將Getting Started詳細的翻譯了一遍,結合上英文,再去理解,就比較容易了。
3.ES的中文翻譯社區地址(ES權威指南)
https://es.xiaoleilu.com/index.html
這ES權威指南書籍的電子文檔,這個網站已經翻譯了很多章節的內容,如果你對博客中給出的翻譯不滿意,可以結合本網站學習。這個網站有個毛病,不知道是電腦字庫渲染問題還是文檔本身的問題,翻譯中會有很多的字是錯的。另一個毛病便是切換文檔時需要等待很久,因此,需要你有足夠的耐心。ES權威指南有一個最大的優點,它選擇人們經常用的東西翻譯,這給開發帶來了極大的便利。
4.ES英文官網文檔學習路線
如果你急需在較短的時間內使用ES,那麼你可以按着下面的路線進行快速入門,並且學習一些高級的東西。下面的學習路線是擁有多年開發經驗同事給我規劃的,希望對你有用。我公司使用的ES版本是2.3,並且封裝了自己的框架。因此,你在查看文檔時,也需要查看相應的版本,版本不同,文檔的結構會有所變化。
① Getting Started 裏的所有內容;
② Setup Elasticsearch 裏的所有內容;
③ Document APIs 裏的所有內容;
④ Search APIs 下的 Search、URI Search、Request Body Search;
⑤ Query DSL 下的 Query and filter context、Match All Query、Full text queries下的Match Query, Compound queries下的 Bool Query, Joining queries下的 Nested Query。
⑥ Term level queries下的 Term Query、Terms Query、Rangge Query。這在查詢時會用到。
⑦ Mapping下Field datatypes下的Array datatype、Binary datatype、Range datatype、Boolean datatype、Date datatype、Object datatype、String datatype、Text datatype;這裏根據自己想買需求可多看一些其他的,這裏講解的是ES所支持的數據類型。
上面給出的,便是我接觸ES的學習路線,說實話,第一次接觸ES,我不僅看完了上面的全部,還看了很多。才把ES弄明白了一點點。
二、搭建ES時遇到的問題
ES的搭建在我看來,懂點Linux的人基本上不成問題,但是像我這種菜菜,就遇到了好多坑。不過我所遇到錯誤的原因都是權限問題。ES官網明確的說了一點,不要使用root用戶啓動,這是致命的。
第二個問題是,ES的壓縮包解壓之後,就可以直接使用了,如果你對文件夾做權限的更改,那麼,啓動的時候就會報找不到Java環境等各種錯誤,起初我以爲是我沒有搭建Java環境,到頭來發現,並不是,遇到這個問題時,使用如下方式解決問題:
[yh@centos bin]$ sudo chown -R elasticsearc安裝文件夾 yh.yh
例如: sudo chown -R elasticsearch yaohong.yaohong(這個是用戶)
執行以上命令之後,那麼Elasticsearch就可以正常啓動了,如果遇到別的問題,那麼不好意思,百度吧!
啓動ES的方法
解壓文件之後,進入bin目錄,然後執行以下命令,ES便啓動了。
[yh@centos bin]$ ./elasticsearch
如果想在後臺啓動,使用-d參數,命令如下:
[yh@centos bin]$ ./elasticsearch -d
如果不是後臺啓動,你將看到如下信息,如果沒有如下信息,說明ES啓動失敗了!
[2017-04-24 10:36:53,706][INFO ][node ] [Mist Mistress] version[2.4.4], pid[12159], build[fcbb46d/2017-01-03T11:33:16Z]
[2017-04-24 10:36:53,707][INFO ][node ] [Mist Mistress] initializing ...
[2017-04-24 10:36:55,021][INFO ][plugins ] [Mist Mistress] modules [lang-groovy, reindex, lang-expression], plugins [], sites []
[2017-04-24 10:36:55,069][INFO ][env ] [Mist Mistress] using [1] data paths, mounts [[/ (rootfs)]], net usable_space [11.9gb], net total_space [19.5gb], spins? [unknown], types [rootfs]
[2017-04-24 10:36:55,069][INFO ][env ] [Mist Mistress] heap size [1015.6mb], compressed ordinary object pointers [true]
[2017-04-24 10:36:59,763][INFO ][node ] [Mist Mistress] initialized
[2017-04-24 10:36:59,770][INFO ][node ] [Mist Mistress] starting ...
[2017-04-24 10:37:00,014][INFO ][transport ] [Mist Mistress] publish_address {127.0.0.1:9301}, bound_addresses {127.0.0.1:9301}
[2017-04-24 10:37:00,031][INFO ][discovery ] [Mist Mistress] elasticsearch/a-VF8e_uQZ2y0k-wB_eeug
[2017-04-24 10:37:03,389][INFO ][cluster.service ] [Mist Mistress] detected_master {Anelle}{K2u_6PgETsG5BifXQxfO2w}{127.0.0.1}{127.0.0.1:9300}, added {{Anelle}{K2u_6PgETsG5BifXQxfO2w}{127.0.0.1}{127.0.0.1:9300},}, reason: zen-disco-receive(from master [{Anelle}{K2u_6PgETsG5BifXQxfO2w}{127.0.0.1}{127.0.0.1:9300}])
[2017-04-24 10:37:03,855][INFO ][http ] [Mist Mistress] publish_address {127.0.0.1:9201}, bound_addresses {127.0.0.1:9201}
[2017-04-24 10:37:03,860][INFO ][node ] [Mist Mistress] started
如果你是後臺啓動,將看不到任何輸出,除非出錯了,可以使用如下命令,查看都端口情況:
[yh@centos bin]$ netstat -apn | grep 9200
三、一些ES的概念
1.ES中的Bool查詢有三種狀態,分別是must,should,must_not。說實話,我都懷疑我的語文是體育老師教的,當時我看到這個時,想了很久都沒有搞懂。在加上看的是英文,我更懵逼了。如果你有SQL語言的基礎,那麼就很好理解了。
① must 相當於 SQL 的 and條件,比如你用SQL查詢價格,你會寫出如下sql語句:
select * from table_name where id = 1000 and price = 50;
這樣的語句就相當於ES的must查詢。
② shoud相當於SQL 的 or條件,例如:
select * from table_name where id = 1000 or price = 50;
③ must_not 相當於SQL的not in,例如:
select * from table_name where id not in(1000);
must_not即不包含某某。
對於大於等於,區間值等,API的文檔中有詳細的說明。
如果你想知道更多的概念,那麼請點擊我上面說明的連接地址,他們講解的更清楚,我不在造輪子。
四、應用思路
1.學習ES的相關基礎知識和概念;
2.瞭解項目需求;
3.考慮ES的所需功能是否能夠解決當前的項目需求;
4.考慮之後,部署ES,如果能力可能,可自行封裝一層,原生的ES操作比較複雜,數據拼接容易出錯且不好維護;
5.編寫Mapping,建立索引;
6.導入數據;
7.數據導入之後便可查詢、重索引等各種測試,如果沒有數據,一切都是瞎忙活;
8.應用到實際項目中。
由於小編也是剛接觸ES不久,因此上面說的步驟不一定適合你,上面步驟是我經驗豐厚的同事教的方法,我根據他教的方法終結出來的。這裏我只是提供我自己學習的路線,你可以自己根據自己的能力調整。
五、Mapping映射(高級)
雖然ES可以根據數據的格式自動創建Mapping,他將所有的對象都映射成Object,但很多時候是不滿足項目需求的,基礎的Mapping映射我就不解釋,官方文檔比我說得清楚,不需要你看英文說明,僅看代碼就秒懂,並且網上一搜一大堆。我在做項目時遇到的映射,在網上並沒有找到。首先,請看下面這個json數據,我們需求是,能夠查詢字段”schedule_info”中時間區間或者日期區間,看到這個json你也許知道,sql是做不到的(”schedule_info字段是以json字符串保存到數據庫中的”),而ES是可以的,但是ES要實現這個功能,需要用到Nested查詢,那麼在寫Mapping時,就必須將其轉化爲對象。
{
"id": 1000017,
"status": 0,
"name": "HHH",
"daily_budget": 410000,
"schedule_info": {
"date": [
{
"start": "2017-04-20",
"end": "2017-04-20"
},
{
"start": "2017-04-20",
"end": "2017-04-20"
}
],
"time": [
{
"start": "00:00",
"end": "23:59"
},
{
"start": "00:00",
"end": "23:59"
}
]
},
"serving_speed": 0,
"create_time": 1492694481227,
"start_schedule": 1492694481227,
"end_schedule": 1499994481227,
"create_user": "admin",
"update_user": "unknown"
}
“schedule_info”字段包含了一個date和time兩個屬性,而這兩個屬性是都是數據,那麼在寫mapping時,該怎麼寫,我在做項目時,琢磨了一天,才弄明白ES的對象嵌套映射。下面是我的mapping。
{
"order": 0,
"template": "Yaohong-plan-*",
"settings": {
"index": {
"number_of_replicas": "1",
"number_of_shards": "5",
"refresh_interval": "1s"
}
},
"mappings": {
"_default_": {
"properties": {
"update_user": {
"index": "not_analyzed",
"type": "string"
},
"status": {
"type": "integer"
},
"end_schedule": {
"format": "yyyy-MM-dd HH:mm:ss||epoch_millis",
"type": "date"
},
"serving_speed": {
"type": "integer"
},
"id": {
"type": "long"
},
"update_time": {
"format": "yyyy-MM-dd HH:mm:ss||epoch_millis",
"type": "date"
},
"start_schedule": {
"format": "yyyy-MM-dd HH:mm:ss||epoch_millis",
"type": "date"
},
"daily_budget": {
"type": "integer"
},
"create_time": {
"format": "yyyy-MM-dd HH:mm:ss||epoch_millis",
"type": "date"
},
"create_user": {
"index": "not_analyzed",
"type": "string"
},
"schedule_info": {
"type":"nested",
"properties":{
"date":{
"properties":{
"start":{
"type":"date",
"format":"yyyy-MM-dd||epoch_millis"
},
"end":{
"type":"date",
"format":"yyyy-MM-dd||epoch_millis"
}
}
},
"time":{
"properties":{
"start":{
"type":"integer"
},
"end":{
"type":"integer"
}
}
}
}
}
},
"_all": {
"enabled": false
}
}
},
"aliases": {
"Yaohong-plan-active": {}
}
}
那麼如果我需要查詢日期在某個區間怎麼去查詢呢?請看下面的查詢語句:
{
"bool" : {
"must" : [ {
"term" : {
"status" : "0"
}
}, {
"nested" : {
"query" : {
"bool" : {
"filter" : [ {
"range" : {
"schedule_info.date.start" : {
"from" : "2017-03-05",
"to" : null,
"format" : "yyyy-MM-dd",
"include_lower" : true,
"include_upper" : true
}
}
}, {
"range" : {
"schedule_info.date.end" : {
"from" : null,
"to" : "2017-09-12",
"format" : "yyyy-MM-dd",
"include_lower" : true,
"include_upper" : true
}
}
} ]
}
},
"path" : "schedule_info"
}
} ],
"should" : {
"match" : {
"name" : {
"query" : "YangHong",
"type" : "boolean"
}
}
}
}
}
從查詢語句可以看出,ES對對象進行了扁平化的處理方式,如schedule_info.date.endDate,基於別的對象或者是數組的映射,官方文檔都有很詳細的說明,我給出的例子,在官方文檔是沒有的,因此分享給大家,當你看完這個例子,相信別的複雜映射都可以解決了。
另外需要說明的是,ES查詢日期類型時,其查詢格式必須與Mapping映射時的格式一模一樣,否則會出錯,對於單純的時間查詢,需要轉化成可比較的數據類型,像“06.30”這樣的時間數據,ES會以字符串的形式比較,從而得不到正確的結果。在此例子中,我將時間轉化成爲了整型,方便查找時間區間。
由於小編能力有限,如有錯誤,請指正,謝謝合作!