Elasticsearch【快速入门】
?
前言:畢設項目還要求加了這個做大數(shù)據(jù)搜索,正好自己也比較感興趣,就一起來學習學習吧!
Elasticsearch 簡介
Elasticsearch?是一個分布式、RESTful 風格的搜索和數(shù)據(jù)分析引擎,能夠解決不斷涌現(xiàn)出的各種用例。作為 Elastic Stack 的核心,它集中存儲您的數(shù)據(jù),幫助您發(fā)現(xiàn)意料之中以及意料之外的情況。
查詢
保持好奇心。從數(shù)據(jù)中探尋各種問題的答案。
通過 Elasticsearch,您能夠執(zhí)行及合并多種類型的搜索(結(jié)構(gòu)化數(shù)據(jù)、非結(jié)構(gòu)化數(shù)據(jù)、地理位置、指標),搜索方式隨心而變。先從一個簡單的問題出發(fā),試試看能夠從中發(fā)現(xiàn)些什么。
分析
大處著眼,全局在握。
找到與查詢最匹配的十個文檔是一回事。但如果面對的是十億行日志,又該如何解讀呢?Elasticsearch 聚合讓您能夠從大處著眼,探索數(shù)據(jù)的趨勢和模式。
速度
?
可擴展性
?
彈性
?
靈活性
?
操作的樂趣
?
客戶端庫
使用您自己的編程語言與 Elasticsearch 進行交互
Elasticsearch 使用的是標準的 RESTful 風格的 API 和 JSON。此外,我們還構(gòu)建和維護了很多其他語言的客戶端,例如?Java、Python、.NET、SQL 和 PHP。與此同時,我們的社區(qū)也貢獻了很多客戶端。這些客戶端使用起來簡單自然,而且就像 Elasticsearch 一樣,不會對您的使用方式進行限制。
Java:
RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("localhost", 9200, "http"))); SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); searchSourceBuilder.query(QueryBuilders.matchAllQuery()); searchSourceBuilder.aggregation(AggregationBuilders.terms("top_10_states").field("state").size(10)); SearchRequest searchRequest = new SearchRequest(); searchRequest.indices("social-*"); searchRequest.source(searchSourceBuilder); SearchResponse searchResponse = client.search(searchRequest);盡享強大功能
?
HADOOP 和 SPRAK
?
照例來說應該是去扒官網(wǎng),結(jié)果一搜就驚了,這官網(wǎng)也忒得勁兒了吧,竟然提供中文版本而且還有中文版本的文檔,友好友好,我看了好長一會兒才反應過來自己還有博客要寫.咳咳,上面的內(nèi)容都是摘自官網(wǎng)順便附一個官網(wǎng)鏈接:https://www.elastic.co/cn/products/elasticsearch
另外還有一個關于 Elasticsearch 來源很有趣的故事在這里分享一下:
回憶時光
許多年前,一個剛結(jié)婚的名叫 Shay Banon 的失業(yè)開發(fā)者,跟著他的妻子去了倫敦,他的妻子在那里學習廚師。 在尋找一個賺錢的工作的時候,為了給他的妻子做一個食譜搜索引擎,他開始使用 Lucene 的一個早期版本。
直接使用 Lucene 是很難的,因此 Shay 開始做一個抽象層,Java 開發(fā)者使用它可以很簡單的給他們的程序添加搜索功能。 他發(fā)布了他的第一個開源項目 Compass。
后來 Shay 獲得了一份工作,主要是高性能,分布式環(huán)境下的內(nèi)存數(shù)據(jù)網(wǎng)格。這個對于高性能,實時,分布式搜索引擎的需求尤為突出, 他決定重寫 Compass,把它變?yōu)橐粋€獨立的服務并取名 Elasticsearch。
第一個公開版本在2010年2月發(fā)布,從此以后,Elasticsearch 已經(jīng)成為了 Github 上最活躍的項目之一,他擁有超過300名 contributors(目前736名 contributors )。 一家公司已經(jīng)開始圍繞 Elasticsearch 提供商業(yè)服務,并開發(fā)新的特性,但是,Elasticsearch 將永遠開源并對所有人可用。
據(jù)說,Shay 的妻子還在等著她的食譜搜索引擎…
安裝 Elasticsearch
官網(wǎng)最新版本 Elasticsearch (6.5.4),但是由于自己的環(huán)境使用最新版本的有問題(配合下面的工具 Kibana 有問題..Kibana 啟動不了),所以不得不換成更低版本的 6.2.2,下載外鏈:戳這里,當然你也可以試一下最新的版本:
?
順帶一提:在下載之前你應該確保你的 Java 版本保持在 1.8 及以上(就 1.8 吧..),這是 Elasticsearch 的硬性要求,可以自行打開命令行輸入?java -version?來查看 Java 的版本
下載完成后,可以看到是一個壓縮包,我們直接解壓在 D 盤上,然后打開?bin?目錄下的 elasticsearch.bat 文件
?
等待一段時間后,可以看到小黑框輸出一行 start ,就說明我們的 Elasticsearch 已經(jīng)跑起來了,我們訪問地址:http://127.0.0.1:9200/,看到返回一串 JSON 格式的代碼就說明已經(jīng)成功了:
?
安裝 Kibana
這是一個官方推出的把 Elasticsearch 數(shù)據(jù)可視化的工具,官網(wǎng)在這里:【傳送門】,不過我們現(xiàn)在暫時還用不到那些數(shù)據(jù)分析的東西,不過里面有一個 Dev Tools 的工具可以方便的和 Elasticsearch 服務進行交互,去官網(wǎng)下載了最新版本的 Kibana(6.5.4) 結(jié)果不知道為什么總是啟動不起來,所以換一了一個低版本的(6.2.2)正常,給個下載外鏈:下載點這里,你們也可以去官網(wǎng)試試能不能把最新的跑起來:
?
解壓到 D 盤(意外的有點慢..),同樣打開目錄下的bin\kibana.bat:
?
等待一段時間后就可以看到提示信息,運行在 5601 端口,我們訪問地址?http://localhost:5601/app/kibana#/dev_tools/console?_g=()?可以成功進入到 Dev-tools 界面:
?
點擊 【Get to work】,然后在控制臺輸入?GET /_cat/health?v?查看服務器狀態(tài),可以在右側(cè)返回的結(jié)果中看到?green?即表示服務器狀態(tài)目前是健康的:
?
快速入門
一、基礎概念-快速入門
節(jié)點 Node、集群 Cluster 和分片 Shards
ElasticSearch 是分布式數(shù)據(jù)庫,允許多臺服務器協(xié)同工作,每臺服務器可以運行多個實例。單個實例稱為一個節(jié)點(node),一組節(jié)點構(gòu)成一個集群(cluster)。分片是底層的工作單元,文檔保存在分片內(nèi),分片又被分配到集群內(nèi)的各個節(jié)點里,每個分片僅保存全部數(shù)據(jù)的一部分。
索引 Index、類型 Type 和文檔 Document
對比我們比較熟悉的 MySQL 數(shù)據(jù)庫:
index → db
type → table
document → row
如果我們要訪問一個文檔元數(shù)據(jù)應該包括囊括?index/type/id?這三種類型,很好理解。
二、使用 RESTful API 與 Elasticsearch 進行交互
所有其他語言可以使用 RESTful API 通過端口?9200?和 Elasticsearch 進行通信,你可以用你最喜愛的 web 客戶端訪問 Elasticsearch 。一個 Elasticsearch 請求和任何 HTTP 請求一樣由若干相同的部件組成:
curl -X<VERB> '<PROTOCOL>://<HOST>:<PORT>/<PATH>?<QUERY_STRING>' -d '<BODY>'
被?< >?標記的部件:
| VERB | 適當?shù)?HTTP 方法 或 謂詞 :?GET、?POST、?PUT、?HEAD?或者?DELETE。 |
| PROTOCOL | http?或者?https(如果你在 Elasticsearch 前面有一個?https?代理) |
| HOST | Elasticsearch 集群中任意節(jié)點的主機名,或者用?localhost?代表本地機器上的節(jié)點。 |
| PORT | 運行 Elasticsearch HTTP 服務的端口號,默認是?9200?。 |
| PATH | API 的終端路徑(例如?_count?將返回集群中文檔數(shù)量)。Path 可能包含多個組件,例如:_cluster/stats?和?_nodes/stats/jvm?。 |
| QUERY_STRING | 任意可選的查詢字符串參數(shù) (例如??pretty?將格式化地輸出 JSON 返回值,使其更容易閱讀) |
| BODY | 一個 JSON 格式的請求體 (如果請求需要的話) |
就比如計算集群中文檔的數(shù)量,我們可以用這個:
curl -XGET 'http://localhost:9200/_count?pretty' -d ' {"query": {"match_all": {}} } '不過對于安裝了 Kibana 的我們,可以直接在 Kibana 的控制臺輸出以下語句,也是同樣的效果:
GET /_count?pretty {"query": {"match_all": {}} }文檔管理(CRUD)
如果對于 RESTful 不太熟悉的童鞋請右轉(zhuǎn):【傳送門】
增加:
POST /db/user/1 {"username": "wmyskxz1","password": "123456","age": "22" } POST /db/user/2 {"username": "wmyskxz2","password": "123456","age": "22" }這一段代碼稍微解釋一下,這其實就往索引為?db?類型為?user?的數(shù)據(jù)庫中插入一條?id?為 1 的一條數(shù)據(jù),這條數(shù)據(jù)其實就相當于一個擁有?username/password/age?三個屬性的一個實體,就是 JSON 數(shù)據(jù)
執(zhí)行命令后,Elasticsearch 返回如下數(shù)據(jù):
# POST /db/user/1 {"_index": "db","_type": "user","_id": "1","_version": 1,"result": "created","_shards": {"total": 2,"successful": 1,"failed": 0},"_seq_no": 2,"_primary_term": 1 }# POST /db/user/2 {"_index": "db","_type": "user","_id": "2","_version": 1,"result": "created","_shards": {"total": 2,"successful": 1,"failed": 0},"_seq_no": 1,"_primary_term": 1 }version?是版本號的意思,當我們執(zhí)行操作會自動加 1
刪除:
DELETE /db/user/1Elasticsearch 返回數(shù)據(jù)如下:
{"_index": "db","_type": "user","_id": "1","_version": 2,"result": "deleted","_shards": {"total": 2,"successful": 1,"failed": 0},"_seq_no": 1,"_primary_term": 1 }這里就可以看到?version?變成了 2
修改:
PUT /db/user/2 {"username": "wmyskxz3","password": "123456","age": "22" }Elasticsearch 返回數(shù)據(jù)如下:
{"_index": "db","_type": "user","_id": "2","_version": 2,"result": "updated","_shards": {"total": 2,"successful": 1,"failed": 0},"_seq_no": 2,"_primary_term": 1 }查詢:
GET /db/user/2返回數(shù)據(jù)如下:
{"_index": "db","_type": "user","_id": "2","_version": 2,"found": true,"_source": {"username": "wmyskxz3","password": "123456","age": "22"} }搜索
上面我們已經(jīng)演示了基本的文檔 CRUD 功能,然而 Elasticsearch 的核心功能是搜索,所以在學習之前,為更好的演示這個功能,我們先往 Elasticsearch 中插入一些數(shù)據(jù):
PUT /movies/movie/1 {"title": "The Godfather","director": "Francis Ford Coppola","year": 1972,"genres": ["Crime","Drama"] }PUT /movies/movie/2 {"title": "Lawrence of Arabia","director": "David Lean","year": 1962,"genres": ["Adventure","Biography","Drama"] }PUT /movies/movie/3 {"title": "To Kill a Mockingbird","director": "Robert Mulligan","year": 1962,"genres": ["Crime","Drama","Mystery"] }PUT /movies/movie/4 {"title": "Apocalypse Now","director": "Francis Ford Coppola","year": 1979,"genres": ["Drama","War"] }PUT /movies/movie/5 {"title": "Kill Bill: Vol. 1","director": "Quentin Tarantino","year": 2003,"genres": ["Action","Crime","Thriller"] }PUT /movies/movie/6 {"title": "The Assassination of Jesse James by the Coward Robert Ford","director": "Andrew Dominik","year": 2007,"genres": ["Biography","Crime","Drama"] }**_search端點**
現(xiàn)在已經(jīng)把一些電影信息放入了索引,可以通過搜索看看是否可找到它們。 為了使用 ElasticSearch 進行搜索,我們使用?_search?端點,可選擇使用索引和類型。也就是說,按照以下模式向URL發(fā)出請求:<index>/<type>/_search。其中,index?和?type?都是可選的。
換句話說,為了搜索電影,可以對以下任一URL進行POST請求:
- http://localhost:9200/_search?- 搜索所有索引和所有類型。
- http://localhost:9200/movies/_search?- 在電影索引中搜索所有類型
- http://localhost:9200/movies/movie/_search?- 在電影索引中顯式搜索電影類型的文檔。
搜索請求正文和ElasticSearch查詢DSL
如果只是發(fā)送一個請求到上面的URL,我們會得到所有的電影信息。為了創(chuàng)建更有用的搜索請求,還需要向請求正文中提供查詢。 請求正文是一個JSON對象,除了其它屬性以外,它還要包含一個名稱為?“query”?的屬性,這就可使用ElasticSearch的查詢DSL。
{"query": {//Query DSL here} }你可能想知道查詢DSL是什么。它是ElasticSearch自己基于JSON的域特定語言,可以在其中表達查詢和過濾器。你可以把它簡單同SQL對應起來,就相當于是條件語句吧。
基本自由文本搜索:
查詢DSL具有一長列不同類型的查詢可以使用。 對于“普通”自由文本搜索,最有可能想使用一個名稱為“查詢字符串查詢”。
查詢字符串查詢是一個高級查詢,有很多不同的選項,ElasticSearch將解析和轉(zhuǎn)換為更簡單的查詢樹。如果忽略了所有的可選參數(shù),并且只需要給它一個字符串用于搜索,它可以很容易使用。
現(xiàn)在嘗試在兩部電影的標題中搜索有“kill”這個詞的電影信息:
GET /_search {"query": {"query_string": {"query": "kill"}} }執(zhí)行上面的請求并查看結(jié)果,如下所示 -
?
正如預期的,得到兩個命中結(jié)果,每個電影的標題中都帶有“kill”單詞。再看看另一種情況,在特定字段中搜索。
指定搜索的字段
在前面的例子中,使用了一個非常簡單的查詢,一個只有一個屬性?“query”?的查詢字符串查詢。 如前所述,查詢字符串查詢有一些可以指定設置,如果不使用,它將會使用默認的設置值。
這樣的設置稱為“fields”,可用于指定要搜索的字段列表。如果不使用“fields”字段,ElasticSearch查詢將默認自動生成的名為?“_all”?的特殊字段,來基于所有文檔中的各個字段匹配搜索。
為了做到這一點,修改以前的搜索請求正文,以便查詢字符串查詢有一個?fields?屬性用來要搜索的字段數(shù)組:
GET /_search {"query": {"query_string": {"query": "ford","fields": ["title"]}} }執(zhí)行上面查詢它,看看會有什么結(jié)果(應該只匹配到 1 行數(shù)據(jù)):
?
正如預期的得到一個命中,電影的標題中的單詞“ford”。現(xiàn)在,從查詢中移除fields屬性,應該能匹配到 3 行數(shù)據(jù):
?
過濾
前面已經(jīng)介紹了幾個簡單的自由文本搜索查詢。現(xiàn)在來看看另一個示例,搜索?“drama”,不明確指定字段,如下查詢 -
GET /_search {"query": {"query_string": {"query": "drama"}} }因為在索引中有五部電影在?_all?字段(從類別字段)中包含單詞?“drama”,所以得到了上述查詢的?5?個命中。 現(xiàn)在,想象一下,如果我們想限制這些命中為只是?1962?年發(fā)布的電影。要做到這點,需要應用一個過濾器,要求?“year”?字段等于?1962。要添加過濾器,修改搜索請求正文,以便當前的頂級查詢(查詢字符串查詢)包含在過濾的查詢中:
{"query": {"filtered": {"query": {"query_string": {"query": "drama"}},"filter": {//Filter to apply to the query}}} }過濾的查詢是具有兩個屬性(query和filter)的查詢。執(zhí)行時,它使用過濾器過濾查詢的結(jié)果。要完成這樣的查詢還需要添加一個過濾器,要求year字段的值為1962。
ElasticSearch查詢DSL有各種各樣的過濾器可供選擇。對于這個簡單的情況,某個字段應該匹配一個特定的值,一個條件過濾器就能很好地完成工作。
"filter": {"term": { "year": 1962 } }完整的搜索請求如下所示:
GET /_search {"query": {"filtered": {"query": {"query_string": {"query": "drama"}},"filter": {"term": {"year": 1962}}}} }當執(zhí)行上面請求,只得到兩個命中,這個兩個命中的數(shù)據(jù)的?year?字段的值都是等于?1962。
無需查詢即可進行過濾
在上面的示例中,使用過濾器限制查詢字符串查詢的結(jié)果。如果想要做的是應用一個過濾器呢? 也就是說,我們希望所有電影符合一定的標準。
在這種情況下,我們?nèi)匀辉谒阉髡埱笳闹惺褂?“query”?屬性。但是,我們不能只是添加一個過濾器,需要將它包裝在某種查詢中。
一個解決方案是修改當前的搜索請求,替換查詢字符串?query?過濾查詢中的?match_all?查詢,這是一個查詢,只是匹配一切。類似下面這個:
GET /_search {"query": {"filtered": {"query": {"match_all": {}},"filter": {"term": {"year": 1962}}}} }另一個更簡單的方法是使用常數(shù)分數(shù)查詢:
GET /_search {"query": {"constant_score": {"filter": {"term": {"year": 1962}}}} }參考文章:Elasticsearch入門教程、Elasticsearch官方文檔、?ElasticSearch 快速上手學習入門教程
三、集成 SpringBoot 簡單示例
第一步:新建 SpringBoot 項目
pom包依賴:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId> </dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope> </dependency> <!-- Elasticsearch支持 --> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-elasticsearch</artifactId> </dependency>application.properties:
spring.data.elasticsearch.cluster-nodes=127.0.0.1:9300第二步:新建實體類
User類:
@Document(indexName = "users", type = "user") public class User {private int id;private String username;private String password;private int age;/** getter and setter */ }第三步:Dao 層
UserDao:
import com.wmyskxz.demo.domain.User; import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;public interface UserDao extends ElasticsearchRepository<User, Integer> { }第四步:Controller 層
這里緊緊是為了演示,所以就省略 service 層,當然 CRUD 不能少:
@RestController public class UserController {@AutowiredUserDao userDao;@PostMapping("/addUser")public String addUser(String username, String password, Integer age) {User user = new User();user.setUsername(username);user.setPassword(password);user.setAge(age);return String.valueOf(userDao.save(user).getId());// 返回id做驗證}@DeleteMapping("/deleteUser")public String deleteUser(Integer id) {userDao.deleteById(id);return "Success!";}@PutMapping("/updateUser")public String updateUser(Integer id, String username, String password, Integer age) {User user = new User();user.setId(id);user.setUsername(username);user.setPassword(password);user.setAge(age);return String.valueOf(userDao.save(user).getId());// 返回id做驗證}@GetMapping("/getUser")public User getUser(Integer id) {return userDao.findById(id).get();}@GetMapping("/getAllUsers")public Iterable<User> getAllUsers() {return userDao.findAll();} }第五步:測試
使用 REST 測試工具測試沒有問題,過程我就不給了..bingo!
總結(jié)
其實使用 SpringBoot 來操作 Elasticsearch 的話使用方法有點類似 JPA 了,而且完全可以把 Elasticsearch 當做 SQL 服務器來用,也沒有問題...在各種地方看到了各個大大特別是官方,都快把 Elasticsearch 這款工具吹上天了,對于它方便的集成這一點我倒是有感受,關于速度這方面還沒有很深的感受,慢慢來吧...
按照慣例黏一個尾巴:
歡迎轉(zhuǎn)載,轉(zhuǎn)載請注明出處!
簡書ID:@我沒有三顆心臟
github:wmyskxz
總結(jié)
以上是生活随笔為你收集整理的Elasticsearch【快速入门】的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MongoDB【快速入门】
- 下一篇: Java消息系统简单设计与实现