文章目錄
1.引入
1.1 Luence
Lucene是一個開放源代碼的全文檢索引擎工具包,但它不是一個完整的全文檢索引擎,而是一個全文檢索引擎的架構,提供了完整的查詢引擎和索引引擎,部分文本分析引擎(英文與德文兩種西方語言)。Lucene的目的是爲軟件開發人員提供一個簡單易用的工具包,以方便的在目標系統中實現全文檢索的功能,或者是以此爲基礎建立起完整的全文檢索引擎。
1.2 Solr
Solr是一個基於Luence的企業級全文搜索服務器,它童工了比Luence更加豐富的查詢語言,同時實現了可配置、可擴展,同時對索引和搜索性能進行了優化。Solr可以獨立運行,運行在Jetty、Tomcat等這些Servlet容器中。
Solr 索引的實現方法是用 POST方法向 Solr 服務器發送一個描述 Field 及其內容的 XML 文檔,Solr根據xml文檔添加、刪除、更新索引。Solr 搜索只需要使用提供的Web-service的API接口,來發送 HTTP GET 請求,然後對返回XML、json等格式的查詢結果進行解析,組織頁面佈局。
1.3 ElasticSearch
Elasticsearch是一個基於Lucene的搜索服務器。它提供了一個分佈式多用戶能力的全文搜索引擎,基於RESTful web接口。Elasticsearch是用Java語言開發的,並作爲Apache許可條款下的開放源碼發佈,是一種流行的企業級搜索引擎。Elasticsearch用於雲計算中,能夠達到實時搜索,穩定,可靠,快速,安裝使用方便。官方客戶端在Java、.NET(C#)、PHP、Python、Apache Groovy、Ruby和許多其他語言中都是可用的。根據DB-Engines的排名顯示,Elasticsearch是最受歡迎的企業搜索引擎,其次是Apache Solr,也是基於Lucene。
source: 百度百科
2. ElasticSearch安裝
2.1 雲服務器安裝
2.1.1. docker安裝
-
搜索鏡像:如果
docker search elasticsearch
,或者到docker hub中進行搜索
如果不指定版本可能會無法進行安裝,因此,最好指定安裝的版本號。
-
拉取鏡像
docker pull elasticsearch:7.8.0
-
運行鏡像並進行端口映射
[root@izbp15ffbqqbe97j9dcf5dz ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE docker.io/elasticsearch 7.8.0 121454ddad72 6 days ago 810 MB [root@izbp15ffbqqbe97j9dcf5dz ~]# docker run -e ES_JAVA_OPTS="-Xms512m -Xmx512m" -e "discovery.type=single-node" -d -p 9200:9200 -p 9300:9300 --name ES01 121454ddad72
NOTE:
-e ES_JAVA_OPTS="-Xms512m -Xmx512m"
:只用指定啓動elasticsearch所需的內存大小,elasticsearch默認使用內存大小爲2G,,如果不夠則無法正常啓動。因爲我的雲服務器只有2G的內存,因此,這裏最大可用內存和最小可用內存都爲512m-e "discovery.type=single-node"
:單節點安裝要加上,否則會報ERROR: [1] bootstrap checks failed-p 9200:9200 -p 9300:9300
:進行端口映射,便於遠程訪問
-
查看是否正常運行,可以看到正常運行中
[root@izbp15ffbqqbe97j9dcf5dz ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 200c0b2c5735 121454ddad72 "/tini -- /usr/loc..." 11 minutes ago Up 10 minutes 0.0.0.0:9200->9200/tcp, 0.0.0.0:9300->9300/tcp ES01 afc7a1ab33ce 95bc78c8d15d "docker-entrypoint..." 5 hours ago Up 5 hours 4369/tcp, 5671/tcp, 0.0.0.0:5672->5672/tcp, 15671/tcp, 25672/tcp, 0.0.0.0:15672->15672/tcp rabbitmq 25bd2268623c redis "docker-entrypoint..." 22 hours ago Up 22 hours 0.0.0.0:6379->6379/tcp redis 53b9351e2a7f mysql "docker-entrypoint..." 29 hours ago Up 29 hours 0.0.0.0:3306->3306/tcp, 33060/tcp wizardly_cori [root@izbp15ffbqqbe97j9dcf5dz ~]#
2.1.2 配置安全規則
登錄雲服務器,選擇左側的安全組中的配置規則,手動添加訪問規則:
2.1.3 遠程訪問
使用ip:9200
請求訪問elasticsearch,如果瀏覽器輸出如下信息,表示設置成功。
{
"name" : "200c0b2c5735",
"cluster_name" : "docker-cluster",
"cluster_uuid" : "Ef-bRe0lS8Sgg6s7T4y29g",
"version" : {
"number" : "7.8.0",
"build_flavor" : "default",
"build_type" : "docker",
"build_hash" : "757314695644ea9a1dc2fecd26d1a43856725e65",
"build_date" : "2020-06-14T19:35:50.234439Z",
"build_snapshot" : false,
"lucene_version" : "8.5.1",
"minimum_wire_compatibility_version" : "6.8.0",
"minimum_index_compatibility_version" : "6.0.0-beta1"
},
"tagline" : "You Know, for Search"
}
2.2 windows安裝
2.2.1 elasticsearch安裝
首先到elasticsearch官網下載所需的壓縮包
下載結束後解壓即可用。找到bin目錄下的elasticsearch.bat,雙擊即可在後臺運行elasticsearch服務。接着在瀏覽器中輸入localhost:9200
,如果能看到如下信息,說明elasticsearch正常啓動
{
"name" : "DESKTOP-5UNDPP9",
"cluster_name" : "elasticsearch",
"cluster_uuid" : "BmT8EaJsRZKDAfj34tmJ2A",
"version" : {
"number" : "7.6.1",
"build_flavor" : "default",
"build_type" : "zip",
"build_hash" : "aa751e09be0a5072e8570670309b1f12348f023b",
"build_date" : "2020-02-29T00:15:25.529771Z",
"build_snapshot" : false,
"lucene_version" : "8.4.0",
"minimum_wire_compatibility_version" : "6.8.0",
"minimum_index_compatibility_version" : "6.0.0-beta1"
},
"tagline" : "You Know, for Search"
}
NOTE:
安裝elasticsearch確保JDK已正確安裝
elasticsearch啓動時默認佔用內存大小爲1G,如果想降低所佔內存可到解壓目錄下的config/jvm.options修改其中的
-Xms
和-Xmx
參數,如:-Xms512m -Xmx1512m
2.2.2 head插件安裝
安裝前請確保Nodejs環境已安裝~
首先到elasticsearch-head中下載code的壓縮包,下載完畢後解壓,併到命令行窗口切換到解壓目錄。運行npm install
安裝插件,最後使用npm run start
命令啓動插件。
爲了連接前面安裝的elasticsearch,還需要解決跨域問題。在elasticsearch的解壓目錄下找到config/elasticsearch.yml文件,添加如下設置,並使用UTF-8格式保存。不然可能會出現閃退問題:
http.cors.enabled: true
http.cors.allow-origin: "*"
在瀏覽器中輸入localhost:9100
訪問會看到如下頁面,表示啓動成功。
在Connect左側的地址欄中輸入http://127.0.0.1:9200/
便可連接上elasticsearch。
我使用
http://localhost:9200/
無法連接成功,不知道爲什麼~
2.2.3 安裝ElasticHD
elasticsearch-head實在是不符合現代審美,所以可以選擇安裝ElasticHD,它是一個Elasticsearch 可視化DashBoard, 支持Es監控、實時搜索,Index template快捷替換修改,索引列表信息查看, SQL converts to DSL等。
這裏同樣只介紹通過雲服務器的docker安裝,首先到docker hub上搜索鏡像
通過docker pull containerize/elastichd
命令拉取鏡像:
root@izbp15ffbqqbe97j9dcf5dz ~]# docker pull containerize/elastichd
Using default tag: latest
Trying to pull repository docker.io/containerize/elastichd ...
latest: Pulling from docker.io/containerize/elastichd
43d680a959df: Pull complete
de979aec8d7a: Pull complete
1216b09132aa: Pull complete
Digest: sha256:2b20e180418f3b6d0d37f2be4485244960131a9d6ce1d51ab6afbc6f40685e20
Status: Downloaded newer image for docker.io/containerize/elastichd:latest
通過docker ps
查看正在運行的elasticsearch服務的名字,我這裏是ES01。然後使用docker run -p 9800:9800 -d --link ES01:demo containerize/elastichd
命令安裝,最後使用docker ps
查看是否啓動成功。
[root@izbp15ffbqqbe97j9dcf5dz ~]# docker run -p 9800:9800 -d --link ES01:demo containerize/elastichd
427bdf04b78c49794fc65106074476751d58e939bb43a448785354307e855412
[root@izbp15ffbqqbe97j9dcf5dz ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
427bdf04b78c containerize/elastichd "ElasticHD" 4 seconds ago Up 3 seconds 0.0.0.0:9800->9800/tcp clever_heisenberg
5c09fb35ce4f e2a76963bc18 "/bin/sh -c 'node_..." 4 minutes ago Up 4 minutes 0.0.0.0:9100->9100/tcp ES-Head
200c0b2c5735 121454ddad72 "/tini -- /usr/loc..." 42 hours ago Up 42 hours 0.0.0.0:9200->9200/tcp, 0.0.0.0:9300->9300/tcp ES01
afc7a1ab33ce 95bc78c8d15d "docker-entrypoint..." 47 hours ago Up 47 hours 4369/tcp, 5671/tcp, 0.0.0.0:5672->5672/tcp, 15671/tcp, 25672/tcp, 0.0.0.0:15672->15672/tcp rabbitmq
25bd2268623c redis "docker-entrypoint..." 2 days ago Up 2 days 0.0.0.0:6379->6379/tcp redis
53b9351e2a7f mysql "docker-entrypoint..." 2 days ago Up 2 days 0.0.0.0:3306->3306/tcp, 33060/tcp wizardly_cori
此外,爲了實現遠程訪問,還需要在服務器安全組添加安全規則
配置結束後在瀏覽器輸入http://ip:9800/
,如果訪問成功會看到如下dashboard,並且可以在地址欄中輸入http://ip:9200/
來連接elasticsearch服務。
2.2.4安裝kibana
Kibana是一個針對Elasticsearch的開源分析及可視化平臺,用來搜索、查看交互存儲在Elasticsearch索引中的數據。使用Kibana,可以通過各種圖表進行高級數據分析及展示。Kibana讓海量數據更容易理解。它操作簡單,基於瀏覽器的用戶界面可以快速創建儀表板(dashboard)實時顯示Elasticsearch查詢動態。設置Kibana非常簡單。無需編碼或者額外的基礎架構,幾分鐘內就可以完成Kibana安裝並啓動Elasticsearch索引監測。
首先同樣需要elasticsearch官網下載Kibana的壓縮包,下載結束後解壓即可用。雙擊運行bin/Kbina.bat即可啓動服務,在瀏覽器中輸入localhost:5601
可看到如下界面,說明啓動成功。
3. Spring Boot整合ElasticSearch
3.1 環境搭建
Spring Boot整合elastissearch首先需要引入其依賴:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.8.0</version>
</dependency>
由於Spring Boot自動引入的elasticsearch版本太低,因此,還需要更改elasticsearch的版本,使其和本地安裝的版本一致:
<elasticsearch.version>7.8.0</elasticsearch.version>
elasticsearch針對於Java提供了兩個版本的客戶端來使用它,分別是低版本的RestClient和高版本的RestHighLevelClient,這裏演示使用RestHighLevelClient。
最後在Ioc容器中注入RestHighLevelClient,方便後續的使用。
@Configuration
public class ElasticSearchConfig {
@Bean
public RestHighLevelClient restHighLevelClient(){
RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(
new HttpHost("127.0.0.1", 9200, "http")
)
);
return client;
}
}
3.2 索引操作
添加索引:
@Test
public void testCreateIndex() throws IOException {
// 創建索引請求
CreateIndexRequest request = new CreateIndexRequest("test.index");
// 客戶端執行請求IndicesClient,請求獲得響應
CreateIndexResponse createIndexResponse = restHighLevelClient.indices().
create(request, RequestOptions.DEFAULT);
System.out.println(createIndexResponse);
// org.elasticsearch.client.indices.CreateIndexResponse@274eb315
}
執行單元測試,查看elasticsearch發現test.index已經添加成功。
查詢索引是否存在:
@Test
public void testIndexExist() throws IOException {
GetIndexRequest request = new GetIndexRequest("test.index");
boolean exists = restHighLevelClient.indices().exists(request, RequestOptions.DEFAULT);
System.out.println(exists); // true
}
執行單元測試,控制檯輸出true,表示之前添加的test.index確實存在。
刪除索引
@Test
public void testIndexDelete() throws IOException {
DeleteIndexRequest request = new DeleteIndexRequest("test.index");
AcknowledgedResponse delete = restHighLevelClient.indices().delete(request,
RequestOptions.DEFAULT);
System.out.println(delete.isAcknowledged()); // true
}
執行單元測試,查看elasticsearch發現test.index已經被刪除。
3.3 文檔操作
添加文檔
@Test
public void testAddDoc() throws IOException {
Person person = Person.builder().name("kobe").age(18).build();
// 創建請求
IndexRequest request = new IndexRequest("test.index");
request.id("1");
request.timeout(TimeValue.timeValueMinutes(1));
request.timeout("1s");
// 將數據放入請求
request.source(JSON.toJSONString(person), XContentType.JSON);
// 客戶端發送請求 , 獲取響應的結果
IndexResponse indexResponse = restHighLevelClient.index(request,
RequestOptions.DEFAULT);
System.out.println(indexResponse.toString());
System.out.println(indexResponse.status());
}
執行單元測試,控制檯輸出:
IndexResponse[index=test.index,type=_doc,id=1,version=2,result=updated,seqNo=1,primaryTerm=1,shards={"total":2,"successful":1,"failed":0}]
OK
同時查看elasticsearch,發現確實添加成功。
判斷文檔是否存在
@Test
public void testFetDoc() throws IOException {
GetRequest getRequest = new GetRequest("test.index", "1");
getRequest.fetchSourceContext(new FetchSourceContext(false));
getRequest.storedFields("_none_");
boolean exists = restHighLevelClient.exists(getRequest, RequestOptions.DEFAULT);
System.out.println(exists); // true
}
執行單元測試,控制檯輸出true,表示之前添加的索引是存在的。
獲取文檔信息:
void testGetDocInfo() throws IOException {
GetRequest getRequest = new GetRequest("test.index", "1");
GetResponse getResponse = restHighLevelClient.get(getRequest,
RequestOptions.DEFAULT);
System.out.println(getResponse.getSourceAsString());
System.out.println(getResponse);
}
執行單元測試,控制檯輸出:
{"age":18,"name":"kobe"}
{"_index":"test.index","_type":"_doc","_id":"1","_version":2,"_seq_no":1,
"_primary_term":1,"found":true,"_source":{"age":18,"name":"kobe"}}
更新文檔:
@Test
void testUpdateRequest() throws IOException {
UpdateRequest updateRequest = new UpdateRequest("test.index","1");
updateRequest.timeout("1s");
Person person = Person.builder().name("James").age(34).build();
updateRequest.doc(JSON.toJSONString(person),XContentType.JSON);
UpdateResponse updateResponse = restHighLevelClient.update(updateRequest,
RequestOptions.DEFAULT);
System.out.println(updateResponse.status());
}
執行單元測試,觀察elasticsearch中文檔的情況,發現更新成功。
刪除文檔
@Test
void testDeleteRequest() throws IOException {
DeleteRequest request = new DeleteRequest("test.index","1");
request.timeout("1s");
DeleteResponse deleteResponse = restHighLevelClient.delete(request,
RequestOptions.DEFAULT);
System.out.println(deleteResponse.status());
}
執行單元測試後,觀察elasticsearch中索引的情況,發現此時test.index已經不在了,刪除操作執行成功。
3.4 批量操作
3.4.1 批量添加
@Test
public void testBulkRequest() throws IOException{
BulkRequest bulkRequest = new BulkRequest();
bulkRequest.timeout("1s");
List<Person> list = new ArrayList<>();
Collections.addAll(list, new Person("Kobe", 18),
new Person("James", 34),
new Person("Ball", 24));
for (int i = 0; i < list.size(); i++) {
bulkRequest.add(new IndexRequest("test.index").id(" " + i + 1)
.source(JSON.toJSONString(list.get(i)),XContentType.JSON));
}
BulkResponse bulkResponse = restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
System.out.println(bulkResponse.hasFailures());
}
執行單元測試,查看elasticsearch可以看到所有的文檔均添加到了test.index中。
3.4.2 批量查詢
@Test
void testSearch() throws IOException {
SearchRequest searchRequest = new SearchRequest("test.index");
// 構建搜索條件
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.highlighter();
// 查詢條件,我們可以使用 QueryBuilders 工具來實現
// QueryBuilders.termQuery 精確
// QueryBuilders.matchAllQuery() 匹配所有
TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("age", "18");
// // MatchAllQueryBuilder matchAllQueryBuilder =
// QueryBuilders.matchAllQuery();
sourceBuilder.query(termQueryBuilder);
sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
searchRequest.source(sourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest,
RequestOptions.DEFAULT);
System.out.println(JSON.toJSONString(searchResponse.getHits()));
System.out.println("=================================");
for (SearchHit documentFields : searchResponse.getHits().getHits()) {
System.out.println(documentFields.getSourceAsMap());
}
執行單元測試,控制檯輸出
{"fragment":true,"hits":[{"fields":{},"fragment":false,"highlightFields":{},
"id":" 01","matchedQueries":[],"primaryTerm":0,"rawSortValues":[],
"score":1.0,"seqNo":-2,"sortValues":[],"sourceAsMap":{"name":"Kobe","age":18},
"sourceAsString":"{\"age\":18,\"name\":\"Kobe\"}",
"sourceRef":{"fragment":true},"type":"_doc","version":-1}],
"maxScore":1.0,"totalHits":{"relation":"EQUAL_TO","value":1}}
=================================
{name=Kobe, age=18}