1. 什么是 Elasticsearch
Elastic是一個實時的分布式搜索分析引擎, 它能讓你以一個之前從未有過的速度和規模,去探索你的數據。 它被用作全文檢索、結構化搜索、分析以及這三個功能的組合。
2. 安裝
- Elasticsearch 需要 Java 8 環境
2.1. Windows上運行ElasticSearch
下載安裝包 elasticsearch-6.2.4.zip https://www.elastic.co/downloads/elasticsearch
解壓壓縮包,其目錄結構如下:
從命令窗口運行位於bin文件夾中的elasticsearch.bat,可以使用CTRL + C停止或關閉它
見到xxxx started,那么就是啟動完成了,打開瀏覽器輸入http:\\localhost:9200或http:\\127.0.0.1:9200,如果出現以下文本證明啟動成功了。
{ "name" : "ubH8NDf", "cluster_name" : "elasticsearch", "cluster_uuid" : "sJfrIwlVRBmAArbWRLWyEA", "version" : { "number" : "6.2.4", "build_hash" : "ccec39f", "build_date" : "2018-04-12T20:37:28.497551Z", "build_snapshot" : false, "lucene_version" : "7.2.1", "minimum_wire_compatibility_version" : "5.6.0", "minimum_index_compatibility_version" : "5.0.0" }, "tagline" : "You Know, for Search" }
默認情況下,Elastic 只允許本機訪問,如果需要遠程訪問,可以修改 Elastic 安裝目錄的config/elasticsearch.yml文件,去掉network.host的注釋,將它的值改成0.0.0.0,然后重新啟動 Elastic。
network.host: 0.0.0.0
上面代碼中,設成0.0.0.0讓任何人都可以訪問。線上服務不要這樣設置,要設成具體的 IP。
2.2. 集群搭建
- 准備好三個文件夾
- 修改配置文件:進入到其中某個節點文件中config文件夾中,打開elasticsearch.yml進行配置
- 具體的配置信息參考如下:
節點1的配置信息: http.cors.enabled: true #是否允許跨域 http.cors.allow-origin: "*" cluster.name: my-esLearn #集群名稱,保證唯一 node.name: node-1 #節點名稱,必須不一樣 network.host: 10.118.16.83 #必須為本機的ip地址 http.port: 9200 #服務端口號,在同一機器下必須不一樣 transport.tcpport: 9300 #集群間通信端口號,在同一機器下必須不一樣 #設置集群自動發現機器ip集合 discovery.zen.ping.unicast.hosts: ["10.118.16.83:9300", "10.118.16.83:9301", "10.118.16.83:9302"] 節點2的配置信息: http.cors.enabled: true #是否允許跨域 http.cors.allow-origin: "*" cluster.name: my-esLearn #集群名稱,保證唯一 node.name: node-2 #節點名稱,必須不一樣 network.host: 10.118.16.83 #必須為本機的ip地址 http.port: 9201 #服務端口號,在同一機器下必須不一樣 transport.tcpport: 9301 #集群間通信端口號,在同一機器下必須不一樣 #設置集群自動發現機器ip集合 discovery.zen.ping.unicast.hosts: ["10.118.16.83:9300", "10.118.16.83:9301", "10.118.16.83:9302"] 節點3的配置信息: http.cors.enabled: true #是否允許跨域 http.cors.allow-origin: "*" cluster.name: my-esLearn #集群名稱,保證唯一 node.name: node-3 #節點名稱,必須不一樣 network.host: 10.118.16.83 #必須為本機的ip地址 http.port: 9202 #服務端口號,在同一機器下必須不一樣 transport.tcpport: 9302 #集群間通信端口號,在同一機器下必須不一樣 #設置集群自動發現機器ip集合 discovery.zen.ping.unicast.hosts: ["10.118.16.83:9300", "10.118.16.83:9301", "10.118.16.83:9302"] `
2.3. elasticsearch-head的搭建
解壓已經下載 elasticsearch-head-master.zip,同時確認本機已經安裝好nodejs,cmd->node -v確認nodejs是否安全成功。
解壓壓縮包,切換到elasticsearch-head-master已解壓好的文件夾下。
c:\elasticsearch-head-master>npm install c:\elasticsearch-head-master>npm start
用瀏覽器打開,http://10.118.16.83:9100/, 只要出現下圖界面就證明成功了。
3. 基本概念
-
集群(Cluster)
ES集群是一個或多個節點的集合,它們共同存儲了整個數據集,並提供了聯合索引以及可跨所有節點的搜索能力。多節點組成的集群擁有冗余能力,它可以在一個或幾個節點出現故障時保證服務的整體可用性。集群靠其獨有的名稱進行標識,默認名稱為“elasticsearch”。節點靠其集群名稱來決定加入哪個ES集群,一個節點只能屬一個集群。
-
節點(node)
一個節點是一個邏輯上獨立的服務,可以存儲數據,並參與集群的索引和搜索功能, 一個節點也有唯一的名字,群集通過節點名稱進行管理和通信.
-
主節點
主節點的主要職責是和集群操作相關的內容,如創建或刪除索引,跟蹤哪些節點是群集的一部分,並決定哪些分片分配給相關的節點。穩定的主節點對集群的健康是非常重要的。雖然主節點也可以協調節點,路由搜索和從客戶端新增數據到數據節點,但最好不要使用這些專用的主節點。一個重要的原則是,盡可能做盡量少的工作。
對於大型的生產集群來說,推薦使用一個專門的主節點來控制集群,該節點將不處理任何用戶請求。
-
數據節點
持有數據和倒排索引。
-
客戶端節點
它既不能保持數據也不能成為主節點,該節點可以響應用戶的情況,把相關操作發送到其他節點;客戶端節點會將客戶端請求路由到集群中合適的分片上。對於讀請求來說,協調節點每次會選擇不同的分片處理請求,以實現負載均衡。
-
索引Index
ES將數據存儲於一個或多個索引中,索引是具有類似特性的文檔的集合。類比傳統的關系型數據庫領域來說,索引相當於SQL中的一個數據庫,或者一個數據存儲方案(schema)。索引由其名稱(必須為全小寫字符)進行標識,並通過引用此名稱完成文檔的創建、搜索、更新及刪除操作。一個ES集群中可以按需創建任意數目的索引。每個 Index (即數據庫)的名字必須是小寫。
下面的命令可以查看當前節點的所有 Index
$ curl -X GET 'http://10.118.16.83:9200/_cat/indices?v'
-
文檔類型(Type)
索引內部的邏輯分區(category/partition),然而其意義完全取決於用戶需求。因此,一個索引內部可定義一個或多個類型(type)。一般來說,類型就是為那些擁有相同的域的文檔做的預定義。例如,在索引中,可以定義一個用於存儲用戶數據的類型,一個存儲日志數據的類型,以及一個存儲評論數據的類型。類比傳統的關系型數據庫領域來說,類型相當於“表”
-
文檔Document
Lucene索引和搜索的原子單位,它是包含了一個或多個域的容器,基於JSON格式進行表示。文檔由一個或多個域組成,每個域擁有一個名字及一個或多個值,有多個值的域通常稱為“多值域”。每個文檔可以存儲不同的域集,但同一類型下的文檔至應該有某種程度上的相似之處。相當於數據庫的“記錄”,例如:

{ "user": "張三", "title": "工程師", "desc": "數據庫管理" }
同一個 Index 里面的 Document,不要求有相同的結構(scheme),但是最好保持相同,這樣有利於提高搜索效率。
-
Mapping
相當於數據庫中的schema,用來約束字段的類型,不過 Elastic的 mapping 可以自動根據數據創建
ES中,所有的文檔在存儲之前都要首先進行分析。用戶可根據需要定義如何將文本分割成token、哪些token應該被過濾掉,以及哪些文本需要進行額外處理等等。
分片(shard) :ES的“分片(shard)”機制可將一個索引內部的數據分布地存儲於多個節點,它通過將一個索引切分為多個底層物理的Lucene索引完成索引數據的分割存儲功能,這每一個物理的Lucene索引稱為一個分片(shard)。
每個分片其內部都是一個全功能且獨立的索引,因此可由集群中的任何主機存儲。創建索引時,用戶可指定其分片的數量,默認數量為5個
4. 數據操作
4.1. 文檔更新
4.1.1. 新增
向指定的 /Index/Type 發送 PUT 請求,就可以在 Index 里面新增一條記錄。

$ curl -H "Content-Type:application/json" -X PUT '10.118.16.83:9200/megacorp/employee/1' -d '
{
"first_name" : "John",
"last_name" : "Smith",
"age" : 25,
"about" : "I love to go rock climbing",
"interests": [ "sports", "music" ]
}'
返回:

{ "_index": "megacorp", "_type": "employee", "_id": "1", "_version": 1, "result": "created", "_shards": { "total": 2, "successful": 1, "failed": 0 }, "_seq_no": 0, "_primary_term": 1 }
若不指定id, 則改為Post請求 。id字段就是一個隨機字符串。
再新增兩條:

$ curl -H "Content-Type:application/json" -X PUT '10.118.16.83:9200/megacorp/employee/2' -d ' { "first_name" : "Jane", "last_name" : "Smith", "age" : 32, "about" : "I like to collect rock albums", "interests": [ "music" ] }' $ curl -H "Content-Type:application/json" -X PUT '10.118.16.83:9200/megacorp/employee/3' -d ' { "first_name" : "Douglas", "last_name" : "Fir", "age" : 35, "about": "I like to build cabinets", "interests": [ "forestry" ] }'
4.1.2. 更新
更新記錄就是使用 PUT 請求,重新發送一次數據。

$ curl -H "Content-Type:application/json" -X PUT '10.118.16.83:9200/megacorp/employee/1' -d '
{
"first_name" : "John",
"last_name" : "Smith",
"age" : 26,
"about" : "I love to go rock climbing",
"interests": [ "sports", "music" ]
}'
返回:

{ "_index": "megacorp", "_type": "employee", "_id": "3", "_version": 2, "result": "updated", "_shards": { "total": 2, "successful": 1, "failed": 0 }, "_seq_no": 1, "_primary_term": 1 }
記錄的 Id 沒變,但是版本(version)從1變成2,操作類型(result)從created變成updated,created字段變成false,因為這次不是新建記錄
4.1.3. 檢索文檔
$ curl '10.118.16.83:9200/megacorp/employee/1'
刪除
刪除記錄就是發出 DELETE 請求
$ curl -X DELETE '10.118.16.83:9200/megacorp/employee/1'
4.2. 返回所有記錄
使用 GET 方法,直接請求/Index/Type/_search,就會返回所有記錄。
- http://10.118.16.83:9200/_search - 搜索所有索引和所有類型。
- http://10.118.16.83:9200/megacorp/_search - 在megacorp索引中搜索所有類型
- http://10.118.16.83:9200/megacorp/employee/_search - 在megacorp索引中顯式搜索employee類型的文檔。

$ curl '10.118.16.83:9200/accounts/person/_search' { "took": 4, "timed_out": false, "_shards": { "total": 5, "successful": 5, "skipped": 0, "failed": 0 }, "hits": { "total": 3, "max_score": 1, "hits": [ { "_index": "megacorp", "_type": "employee", "_id": "2", "_score": 1, "_source": { "first_name": "John", "last_name": "Smith", "age": 25, "about": "I love to go rock climbing", "interests": [ "sports", "music" ] } }, …//此處省略 ] } }
上面代碼中,返回結果的 took字段表示該操作的耗時(單位為毫秒),timed_out字段表示是否超時,hits字段表示命中的記錄,里面子字段的含義如下。
total:返回記錄數,本例是3條。
max_score:最高的匹配程度,本例是1.0。
hits:返回的記錄組成的數組。
返回的記錄中,每條記錄都有一個_score字段,表示匹配的程序,默認是按照這個字段降序排列。
4.3. 匹配查詢
Elastic提供兩種方式:
l Query-string 搜索通過命令非常方便地進行臨時性的即席搜索 ,但它有自身的局限性。
$ curl '10.118.16.83:9200/megacorp/employee/_search?q=last_name:Smith'
l 提供一個豐富靈活的查詢語言叫做 查詢表達式 , 它支持構建更加復雜和健壯的查詢。領域特定語言 (DSL), 指定了使用一個 JSON 請求
$ curl -H "Content-Type:application/json" '10.118.16.83:9200/megacorp/employee/_search' -d ' { "query" : { "match" : { "last_name" : " Smith" }} }'
4.4. 過濾查詢
同樣搜索姓氏為 Smith 的雇員,但這次我們只需要年齡大於 30 的。查詢需要稍作調整,使用過濾器 filter [range ],它支持高效地執行一個結構化查詢。

$ curl -H "Content-Type:application/json" '10.118.16.83:9200/megacorp/employee/_search' -d '
{
"query" : {
"bool": {
"must": {
"match" : {
"last_name" : "smith"
}
},
"filter": {
"range" : {
"age" : { "gt" : 30 }
}
}
}
}
}'
4.5. 全文搜索
截止目前的搜索相對都很簡單:單個姓名,通過年齡過濾。現在嘗試下稍微高級點兒的全文搜索——一項 傳統數據庫確實很難搞定的任務。搜索下所有喜歡攀岩(rock climbing)的雇員。

$ curl -H "Content-Type:application/json" '10.118.16.83:9200/megacorp/employee/_search' -d '
{
"query" : {
"match" : {
"about" : "rock climbing"
}
}
}'
得到兩個匹配的文檔
這是一個很好的案例,闡明了 Elasticsearch 如何 在 全文屬性上搜索並返回相關性最強的結果。Elasticsearch中的 相關性 概念非常重要,也是完全區別於傳統關系型數據庫的一個概念,數據庫中的一條記錄要么匹配要么不匹配。
4.6. 短語搜索
找出一個屬性中的獨立單詞是沒有問題的,但有時候想要精確匹配一系列單詞或者短語 。 比如, 我們想執行這樣一個查詢,僅匹配同時包含 “rock” 和 “climbing” ,並且 二者以短語 “rock climbing” 的形式緊挨着的雇員記錄。
為此對 match 查詢稍作調整,使用一個叫做 match_phrase 的查詢:

$ curl -H "Content-Type:application/json" '10.118.16.83:9200/megacorp/employee/_search' -d '
{
"query" : {
"match_phrase" : {
"about" : "rock climbing"
}
}
}'
4.7. 高亮搜索
許多應用都傾向於在每個搜索結果中 高亮 部分文本片段,以便讓用戶知道為何該文檔符合查詢條件。在 Elasticsearch 中檢索出高亮片段也很容易。
再次執行前面的查詢,並增加一個新的 highlight 參數:

$ curl -H "Content-Type:application/json" '10.118.16.83:9200/megacorp/employee/_search' -d '
{
"query" : {
"match_phrase" : {
"about" : "rock climbing"
}
},
"highlight": {
"fields" : {
"about" : {}
}
}
}'
查詢結果:
4.8. 聚合
Elasticsearch 有一個功能叫聚合(aggregations),允許我們基於數據生成一些精細的分析結果。聚合與 SQL 中的 GROUP BY 類似但更強大。
舉個例子,挖掘出雇員中最受歡迎的興趣愛好:

$ curl -H "Content-Type:application/json" '10.118.16.83:9200/megacorp/employee/_search' -d ' { "aggs": { "all_interests": { "terms": { "field": "interests" }, "aggs": { //為指標新增aggs層 "avg_age": { //指定指標的名字,在返回的結果中也是用這個變量名來儲存數值的 "avg": {//指標參數:平均值 "field": "age" //明確求平均值的字段為'age' } } } } } }'
執行失敗:

{ "error": { "root_cause": [ { "type": "illegal_argument_exception", "reason": "Fielddata is disabled on text fields by default. Set fielddata=true on [interests] in order to load fielddata in memory by uninverting the inverted index. Note that this can however use significant memory." } ], "type": "search_phase_execution_exception", "reason": "all shards failed", "phase": "query", "grouped": true, "failed_shards": [ { "shard": 0, "index": "megacorp", "node": "-Md3f007Q3G6HtdnkXoRiA", "reason": { "type": "illegal_argument_exception", "reason": "Fielddata is disabled on text fields by default. Set fielddata=true on [interests] in order to load fielddata in memory by uninverting the inverted index. Note that this can however use significant memory." } } ], "caused_by": { "type": "illegal_argument_exception", "reason": "Fielddata is disabled on text fields by default. Set fielddata=true on [interests] in order to load fielddata in memory by uninverting the inverted index. Note that this can however use significant memory." } }, "status": 400 }
排序,聚合這些操作用單獨的數據結構(fielddata)緩存到內存里了,需要單獨開啟,官方解釋在此fielddata

$ curl -H "Content-Type:application/json" -X POST '10.118.16.83:9200/megacorp/_mapping/employee' -d '
{
"properties":{
"interests":{
"type":"text",
"fielddata":true
}
}
}'
切記,這里一旦類型錯誤,以后可就麻煩咯
查詢結果:

{"took":40,"timed_out":false,"_shards":{"total":5,"successful":5,"skipped":0,"failed":0},"hits":{"total":4,"max_score":1.0,"hits":[{"_index":"megacorp","_type":"employee","_id":"_cat","_score":1.0,"_source":{ "properties":{ "age":{ "type":"integer", "fielddata":true } } } },{"_index":"megacorp","_type":"employee","_id":"2","_score":1.0,"_source":{ "first_name" : "Jane", "last_name" : "Smith", "age" : 32, "about" : "I like to collect rock albums", "interests": [ "music" ] } },{"_index":"megacorp","_type":"employee","_id":"1","_score":1.0,"_source":{ "first_name" : "John", "last_name" : "Smith", "age" : 25, "about" : "I love to go rock climbing", "interests": [ "sports", "music" ] } },{"_index":"megacorp","_type":"employee","_id":"3","_score":1.0,"_source":{ "first_name" : "Douglas", "last_name" : "Fir", "age" : 35, "about": "I like to build cabinets", "interests": [ "forestry" ] } }]},"aggregations":{"all_interests":{"doc_count_error_upper_bound":0,"sum_other_doc_count":0,"buckets":[{"key":"music","doc_count":2,"avg_age":{"value":28.5}},{"key":"forestry","doc_count":1,"avg_age":{"value":35.0}},{"key":"sports","doc_count":1,"avg_age":{"value":25.0}}]}}}
Java實現

@Test public void aggsTermsQuery() { SearchResponse response = client.prepareSearch("cars") .setTypes("transactions") .addAggregation(AggregationBuilders.terms("all_interests").field("interests") .subAggregation(AggregationBuilders.avg("avg_price") .field("price"))) .setSize(0) .get(); Map<String, Aggregation> aggMap = response.getAggregations().asMap(); StringTerms teamAgg= (StringTerms) aggMap.get("popular_colors"); Iterator<Bucket> teamBucketIt = teamAgg.getBuckets().iterator(); while (teamBucketIt .hasNext()) { Bucket buck = teamBucketIt .next(); //max/min以此類推 logger.info(buck.getKeyAsString() + ", " + buck.getDocCount()); Map<String, Aggregation> subAggMap = buck.getAggregations().asMap(); long avgAgg= (long) ((InternalAvg)subAggMap.get("avg_price")).getValue(); logger.info("avg:{}", avgAgg); } }
4.9. 排序與分頁
Elastic使用sort進行排序,默認一次返回10條結果,可以通過size字段改變這個設置。還可以通過from字段,指定位移。

GET /_search { "query" : { "bool" : { "filter" : { "term" : { "user_id" : 1 }} } }, "sort": { "date": { "order": "desc" }}, "from": 1, "size": 1 }
5. 中文分詞設置
5.1. 安裝分詞插件
注意:安裝對應版本的插件。
下載插件https://github.com/medcl/elasticsearch-analysis-ik/releases
5.2. 使用 IK Analysis
要使用 IK Analysis,需要在文檔類里面,指定相應的分詞器。
ik_max_word 和 ik_smart 區別
ik_max_word: 會將文本做最細粒度的拆分,比如會將“中華人民共和國國歌”拆分為“中華人民共和國,中華人民,中華,華人,人民共和國,人民,人,民,共和國,共和,和,國國,國歌”,會窮盡各種可能的組合;
ik_smart: 會做最粗粒度的拆分,比如會將“中華人民共和國國歌”拆分為“中華人民共和國,國歌”。
具體使用可參考https://github.com/medcl/elasticsearch-analysis-ik

public void highlighter() throws UnknownHostException { String preTags = "<strong>"; String postTags = "</strong>"; HighlightBuilder highlightBuilder = new HighlightBuilder(); highlightBuilder.preTags(preTags);//設置前綴 highlightBuilder.postTags(postTags);//設置后綴 highlightBuilder.field("content"); SearchResponse response = client.prepareSearch("msg") .setTypes("tweet") .setSearchType(SearchType.DFS_QUERY_THEN_FETCH) .setQuery(QueryBuilders.matchQuery("content", "中國")) .highlighter(highlightBuilder) .setFrom(0).setSize(60).setExplain(true) .get(); logger.info("search response is:total=[{}]",response.getHits().getTotalHits()); SearchHits hits = response.getHits(); for (SearchHit hit : hits) { logger.info("{} -- {} -- {}", hit.getId(), hit.getSourceAsString(), hit.getHighlightFields()); } SearchRequestBuilder builder = client.prepareSearch("msg") .setTypes("tweet") .setSearchType(SearchType.DFS_QUERY_THEN_FETCH) .setQuery(QueryBuilders.matchQuery("content", "中國")); }
6. 通過Java程序連接Elasticsearch
需要注意的是,我們通過瀏覽器 http://10.118.16.83:9200 訪問可以正常訪問,這里需要知曉,9200端口是用於Http協議訪問的,如果通過客戶端訪問需要通過9300端口才可以訪問
pom.xml添加依賴

<!-- Elasticsearch核心依賴包 --> <dependency> <groupId>org.elasticsearch.client</groupId> <artifactId>transport</artifactId> <version>6.2.4</version> </dependency> <!-- 日志依賴 --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.21</version> <scope>test</scope> </dependency> <!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-core --> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>2.8.2</version> </dependency>
6.1. 單點

import java.net.InetAddress; import java.net.UnknownHostException; import org.elasticsearch.client.transport.TransportClient; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.transport.TransportAddress; import org.elasticsearch.transport.client.PreBuiltTransportClient; import org.junit.Test; public class ElasticsearchTest1 { public static final String HOST = "127.0.0.1"; public static final int PORT = 9200; //http請求的端口是9200,客戶端是9300 @SuppressWarnings("resource") @Test public void test1() throws UnknownHostException { TransportClient client = new PreBuiltTransportClient(Settings.EMPTY).addTransportAddress( new TransportAddress(InetAddress.getByName(HOST), PORT)); System.out.println("Elasticssearch connect info:" + client.toString()); client.close(); } }
6.2. 集群

import java.io.IOException; import java.net.InetAddress; import java.net.UnknownHostException; import org.elasticsearch.action.index.IndexResponse; import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.action.search.SearchType; import org.elasticsearch.client.transport.TransportClient; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.transport.TransportAddress; import org.elasticsearch.common.xcontent.XContentFactory; import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.search.SearchHit; import org.elasticsearch.search.SearchHits; import org.elasticsearch.transport.client.PreBuiltTransportClient; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class ElasticsearchTest2 { public static final String HOST = "10.118.16.83"; public static final int PORT = 9300; //http請求的端口是9200,客戶端是9300 private TransportClient client = null; private Logger logger = LoggerFactory.getLogger(ElasticsearchTest2.class); public static final String CLUSTER_NAME = "my-esLearn"; //實例名稱 //1.設置集群名稱:默認是elasticsearch,並設置client.transport.sniff為true,使客戶端嗅探整個集群狀態,把集群中的其他機器IP加入到客戶端中 private static Settings settings = Settings.builder() .put("cluster.name",CLUSTER_NAME) .put("client.transport.sniff", true) .build(); /** * 獲取客戶端連接信息 * @Title: getConnect * @author ld * @date 2018-05-03 * @return void * @throws UnknownHostException */ @SuppressWarnings("resource") @Before public void getConnect() throws UnknownHostException { client = new PreBuiltTransportClient(settings).addTransportAddress( new TransportAddress(InetAddress.getByName(HOST), PORT)); logger.info("連接信息:" + client.toString()); } @After public void closeConnect() { if (client != null) { client.close(); } } @Test public void test1() throws UnknownHostException { logger.info("Elasticssearch connect info:" + client.toString()); } @Test public void addIndex() throws IOException { IndexResponse response = client.prepareIndex("msg", "tweet", "2").setSource( XContentFactory.jsonBuilder() .startObject() .field("userName", "es") .field("msg", "Hello,Elasticsearch") .field("age", 14) .endObject()).get(); } @Test public void search() { SearchResponse response = client.prepareSearch("msg") .setTypes("tweet") .setSearchType(SearchType.DFS_QUERY_THEN_FETCH) .setQuery(QueryBuilders.matchPhraseQuery("user_name", "es")) .setFrom(0).setSize(60).setExplain(true) .get(); logger.info("search response is:total=[{}]",response.getHits().getTotalHits()); SearchHits hits = response.getHits(); for (SearchHit hit : hits) { logger.info(hit.getId()); logger.info(hit.getSourceAsString()); } } }
7. mysql與elasticsearch同步
可參考elasticsearch與數據庫同步工具Logstash-input-jdbc
8. 與solr的比較
solr |
Elastic |
|
功能 |
官方提供的功能更多 |
官方功能少,但是第三方插件很豐富,擴展能力更強 |
建立索引和查詢效率 |
建立索引的速度和Es差不多,索引建立完成后的檢索速度也很快,但是一邊建立索引一邊搜索會很慢(建立索引時會造成IO阻塞) |
建立索引速度和solr差不多,第一次檢索會比solr慢,之后就快了。一邊建立索引一邊搜索的速度不影響( 索引會先存在內存中,內存不足再寫入磁盤,還有隊列空閑時把索引寫入硬盤) |
支持的數據格式 |
Xml等多種格式 |
json |
分布式管理 |
zookeeper |
自己維護 |
Sharding |
沒有自動shard rebalancing的功能 |
Shard必須一次設置好,之后不能修改,如果要修改則需要重新建立索引 |
高級查詢 |
沒有Query DSL |
有Query DSL,能夠支持更加高級和復雜的查詢語法,而且還可以以此擴展實現類sql語法的查詢 |
搜索 |
傳統搜索應用 |
實時搜索應用(1s的延遲) |
插件 |
不支持插件式開發 |
支持插件式開發,豐富的插件庫 |
9. 在線資源