關於ElasticSearch 搜尋引擎框架
一、ES 相關介紹
1.ES是一個使用Java語言並且基於Lucene編寫的搜尋引擎框架,提供了分散式的全文搜尋功能,還提供了一個統一的基於RESTful風格的Web介面,官方客戶端也對多種語言提供了相應的API。
2.Lucene:它本身就是一個搜尋引擎的底層。屬於Apache的一個頂級專案,和Solr一樣屬於核心搜尋庫
3.分散式:ES主要是為了突出自身的(橫向)高擴充套件能力
4.全文檢索:將一段詞語進行分詞,並且將分出的單個詞語統一的放到一個分詞庫中;在搜尋時,根據關鍵字去分詞庫中檢索,找到匹配的內容。(倒排索引)
5.RESTful風格的Web介面:操作ES很簡單,只需要傳送一個http請求,並且根據請求方式不同和攜帶引數的而不同,執行相應的功能。
6.應用廣泛:Github.com, Wiki,Goldman用ES維護日均近10TB的資料。
二、ElasticSearch和Solr之間的區別
(1).查詢效率:Solr查詢死資料(即資料不可改變,不可多或少)時,檢索速度優先於ES;若資料實時改變時,Solr的查詢效率將大幅降低,而ES檢索效率幾乎不變
(2).搭建叢集:Solr搭建基於Zookeeper來幫助管理,ES本身支援叢集的搭建,不需要第三方介入
(3).文件社群:Solr的社群開始十分火爆,但針對國內的文件並不多;在ES出現之後,ES的相關社群火爆程度直線上升,ES文件也相對更健全
(4).雲端計算和大資料:ES針對現在的主流技術(雲端計算和大資料)的支援和處理相對特別友好。
概念說明:
倒排索引:大致將ES服務分為兩塊(分詞庫和資料區),將存放的資料以一定的方式進行分詞,並且將分詞的內容存放到一個單獨的分詞庫中
<1>.當用戶查詢資料時,會先將使用者的查詢關鍵詞進行分詞
<2>.然後去分詞庫中匹配內容,最終得到資料的索引標識
<3>.根據索引標識去存放資料區拉取指定的資料
三、ES的安裝指引
1.安裝ES & Kibana (ES 的視覺化介面)
說明:具體下載安裝指南此文參考文獻:https://www.jianshu.com/p/05e203ea51af
(1).拉取ES映象
docker pull docker.elastic.co/elasticsearch/elasticsearch:7.5.0
(2).單節點執行ES
docker run -d --restart=always -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" docker.elastic.co/elasticsearch/elasticsearch:7.5.0
(3.1).多節點執行ES
建立一個docker-compose.yml 檔案
version: '2.2'
services:
es01:
image: docker.elastic.co/elasticsearch/elasticsearch:7.5.0
container_name: es01
environment:
- node.name=es01
- cluster.name=es-docker-cluster
- discovery.seed_hosts=es02,es03
- cluster.initial_master_nodes=es01,es02,es03
- bootstrap.memory_lock=true
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
ulimits:
memlock:
soft: -1
hard: -1
volumes:
- data01:/usr/share/elasticsearch/data
ports:
- 9200:9200
networks:
- elastic
es02:
image: docker.elastic.co/elasticsearch/elasticsearch:7.5.0
container_name: es02
environment:
- node.name=es02
- cluster.name=es-docker-cluster
- discovery.seed_hosts=es01,es03
- cluster.initial_master_nodes=es01,es02,es03
- bootstrap.memory_lock=true
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
ulimits:
memlock:
soft: -1
hard: -1
volumes:
- data02:/usr/share/elasticsearch/data
networks:
- elastic
es03:
image: docker.elastic.co/elasticsearch/elasticsearch:7.5.0
container_name: es03
environment:
- node.name=es03
- cluster.name=es-docker-cluster
- discovery.seed_hosts=es01,es02
- cluster.initial_master_nodes=es01,es02,es03
- bootstrap.memory_lock=true
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
ulimits:
memlock:
soft: -1
hard: -1
volumes:
- data03:/usr/share/elasticsearch/data
networks:
- elastic
volumes:
data01:
driver: local
data02:
driver: local
data03:
driver: local
networks:
elastic:
driver: bridge
- 節點 es01 監聽 localhost:9200, es02 和 es03 類似
- 資料卷 data01,data02,data03。可以持久化
- 啟動:docker-compose up
- 停止:docker-compose down
- 停止並刪除資料卷:docker-compose down -v
- 檢視節點是否啟動
curl -X GET "localhost:9200/_cat/nodes?v&pretty"
(3.2)設定vm.max_map_count
grep vm.max_map_count /etc/sysctl.conf
vm.max_map_count=262144
sysctl -w vm.max_map_count=262144
(4)安裝Kibana
docker pull docker.elastic.co/kibana/kibana:7.5.0
(5)設定kibana
docker run --link YOUR_ELASTICSEARCH_CONTAINER_NAME_OR_ID:elasticsearch -p 5601:5601 {docker-repo}:{version}
docker run -d --restart=always --link a72adb9bf49a:elasticsearch -p 5601:5601 docker.elastic.co/kibana/kibana:7.5.0
(6).拉取logstash映象
docker pull docker.elastic.co/logstash/logstash:7.5.0
(7).安裝elasticsearch外掛監控管理
docker pull mobz/elasticsearch-head:5
docker run -d -p 9100:9100 docker.io/mobz/elasticsearch-head:5
(8).安裝ik分詞器
從github專案中查詢ik分詞器:
https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.5.0/elasticsearch-analysis-ik-7.5.0.zip
<1>.先通過docker進入到es容器內部:docker exec -it 容器id bash
<2>.容器內部切換目錄並執行安裝:cd bin/
elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.5.0/elasticsearch-analysis-ik-7.5.0.zip
<3>.說明:國內網站下載比較慢,下載安裝的kibana和ik分詞器的版本都要和elasticsearch保持一致。
(9).重啟ES
通過執行docker命令重啟es: docker restart 容器id
具體實現效果如下所示:
四、ES的資料結構
1.ES服務和MySQL資料庫之間的比較:
ES服務:會搭建叢集,可以建立多個索引,每個索引可以被分成5片儲存,且每個分片都會存在至少一個備份分片;
備份分片預設不會幫助檢索資料,只有當ES檢索壓力特別大的情況下,備份分片才會幫助檢索資料;
備份分片必須存放在不同的伺服器中;
對索引進行分片,可以提高檢索資料的效率,儲存資料容量得到提升。
ES 5.x版本中,一個索引index可以建立多個type;
ES 6.x版本中,一個索引index可以建立一個type;
ES 7.x版本中,一個索引index沒有type。
ES 服務的index類似於MySQL的資料庫;
ES 服務的type類似於MySQL的table;
ES 服務的document類似於MySQL的一行資料存在多個列。
2.常見資料型別
字串型別 :
text:一般被用於全文檢索,將當前Field進行分詞
keyword:意旨關鍵字,當前Field不會被分詞
數值型別:
long
integer
short
byte
double
float
half_float:表示精度比float小一半
scaled_float:根據一個long和scaled來表達一個浮點型 (例如:long-345 scaled-100 即表示3.45)
時間型別:date (針對時間型別指定具體的格式)
布林型別:boolean
二進位制型別:binary (暫時支援64位編碼字符集)
範圍型別:long_range (賦值時,無序指定具體內容,只需要儲存一個範圍即可)
經緯度型別:geo_point (用來儲存經緯度)
ip型別:可以儲存ipv4或ipv6
如果對其他資料型別感興趣,可以參考如下官網進行學習
具體參考文獻:https://www.elastic.co/guide/en/elasticsearch/reference/7.5/mapping.html#field-datatypes
五、操作ES的RESTful語法
1.GET請求
(1).查詢索引資訊:http://ip:port/index
(2).查詢指定文件資訊:http://ip/port/index/type/doc_id
2.POST請求
(1).查詢指定文件 (可在請求體中新增json字串代替查詢條件):http://ip:port/index/type/_search
(2).查詢指定文件 (可在請求體中指定json字串代替修改條件):http://ip/port/index/type/doc_id/_update
3.PUT請求
(1).建立索引 (需要在請求體中指定索引資訊):http://ip:port/index
(2).建立索引時,指定索引文件儲存的屬性資訊:http://ip/port/index/type/_mappings
4.DELETE請求
(1).刪除索引 (需要在請求體中指定索引資訊):http://ip:port/index
(2).刪除指定文件資訊:http://ip/port/index/type/doc_id
五、Java連線ES
1.建立Maven工程
2.匯入依賴:
(1).elasticsearch
(2).elasticsearch 高階API
(3).junit
(4).lombok
<dependencies> <dependency> <groupId>org.elasticsearch</groupId> <artifactId>elasticsearch</artifactId> <version>7.5.0</version> </dependency> <dependency> <groupId>org.elasticsearch.client</groupId> <artifactId>elasticsearch-rest-high-level-client</artifactId> <version>7.5.0</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.16.22</version> </dependency> </dependencies>
3.建立測試類,連線es
public class ESClient { public static RestHighLevelClient getClient(){ //建立HttpHost物件 HttpHost host = new HttpHost("192.168.99.100",9200); //建立 RestClientBuilder RestClientBuilder builder = RestClient.builder(host); //建立 RestHighLevelClient RestHighLevelClient client = new RestHighLevelClient(builder); return client; } }
六、Java操作ES索引
/** * @ClassName Demo2 * @Description Java建立ES索引方式 * @Author AlexChen * @Date 2020/8/23 17:17 * @Version 5.20 * @WebSite www.codeboy.top **/ public class Demo2 { RestHighLevelClient client = ESClient.getClient(); String index = "person"; String type = "man"; @Test public void createIndex() throws IOException { //1.準備關於索引的settings Settings.Builder settings = Settings.builder() .put("number_of_shards",3) .put("number_of_replicas",1); //2.準備關於索引的結構 XContentBuilder mappings = JsonXContent.contentBuilder() .startObject() .startObject("properties") .startObject("name") .field("type","text") .endObject() .startObject("age") .field("type","integer") .endObject() .startObject("birthday") .field("type","date") .field("format","yyyy-MM-dd") .endObject() .endObject() .endObject(); //3.將settings 和 mappings 封裝到一個Request物件 CreateIndexRequest request = new CreateIndexRequest(index) .settings(settings) .mapping(mappings); //4.通過client物件去連線ES並執行建立索引 CreateIndexResponse resp = client.indices().create(request, RequestOptions.DEFAULT); //輸入resp System.out.println("resp>>>"+resp.toString()); } }
public class Demo3 { String index = "person"; RestHighLevelClient client = ESClient.getClient(); /** * 判斷ES指定索引是否存在 */ @Test public void exists() throws IOException { //1.準備request 物件 GetIndexRequest request = new GetIndexRequest(); request.indices(index); //2.通過client操作 boolean exists = client.indices().exists(request, RequestOptions.DEFAULT); //3.輸出結果 System.out.println("返回值:"+exists); } /** * 刪除ES指定索引 */ @Test public void delete() throws IOException { //1.準備request 物件 DeleteIndexRequest request = new DeleteIndexRequest(); request.indices(index); //2.通過client操作 AcknowledgedResponse response = client.indices().delete(request, RequestOptions.DEFAULT); //3.輸出結果 System.out.println("返回值:"+response.isAcknowledged()); } }七、Java操作文件
/** * @ClassName TestDoc * @Description Java操作文件 * @Author AlexChen * @Date 2020/8/23 18:30 * @Version 5.20 * @WebSite www.codeboy.top **/ public class TestDoc { String index = "person"; String type = "man"; ObjectMapper mapper = new ObjectMapper(); RestHighLevelClient client = ESClient.getClient(); /** * 建立一個文件 */ @Test public void createPerson() throws IOException { //1.建立一個Json資料 Person person = new Person(1,"張三",23,new Date()); String json = mapper.writeValueAsString(person); //2.準備一個request物件 IndexRequest request = new IndexRequest(index,type,person.getId().toString()); request.source(json, XContentType.JSON); //3.通過client物件執行新增操作 IndexResponse resp = client.index(request, RequestOptions.DEFAULT); //4.輸出返回結果 System.out.println(resp.getResult().toString()); } /** * 更新一個文件 */ @Test public void updateDoc() throws IOException { //1.建立一個Map物件,指定需要修改的內容 Map<String, Object> doc = new HashMap<String, Object>(); doc.put("name","埃裡克森"); String docId = "1"; //2.建立request物件,封裝資料 UpdateRequest request = new UpdateRequest(index,type,docId); request.doc(doc); //3.通過client物件執行 UpdateResponse update = client.update(request, RequestOptions.DEFAULT); //4.輸出返回結果 System.out.println(update.getGetResult().toString()); } /** * 刪除一個文件 */ @Test public void deleteDoc() throws IOException { //1.封裝request物件,封裝資料 DeleteRequest request = new DeleteRequest(index,type,"1"); //2.通過client物件執行 DeleteResponse response = client.delete(request, RequestOptions.DEFAULT); //3.輸出返回結果 System.out.println(response.getResult().toString()); } /** * 批量新增文件 */ @Test public void batchCreateDoc() throws IOException { //1.準備多個json資料 Person p1 = new Person(1,"張三",23,new Date()); Person p2 = new Person(2,"李四",24,new Date()); Person p3 = new Person(3,"王五",25,new Date()); String json1 = mapper.writeValueAsString(p1); String json2 = mapper.writeValueAsString(p2); String json3 = mapper.writeValueAsString(p3); //2.建立request物件,將準備好的資料封裝進去 BulkRequest request = new BulkRequest(); request.add(new IndexRequest(index,type,p1.getId().toString()).source(json1,XContentType.JSON)); request.add(new IndexRequest(index,type,p2.getId().toString()).source(json2,XContentType.JSON)); request.add(new IndexRequest(index,type,p3.getId().toString()).source(json3,XContentType.JSON)); //3.通過client執行 BulkResponse bulk = client.bulk(request, RequestOptions.DEFAULT); //4.輸出返回結果 System.out.println(bulk.toString()); } /** * 批量刪除文件 */ @Test public void batchDeleteDoc() throws IOException { //1.封裝request物件 BulkRequest request = new BulkRequest(); request.add(new DeleteRequest(index,type,"1")); request.add(new DeleteRequest(index,type,"2")); request.add(new DeleteRequest(index,type,"3")); //2.通過client執行 BulkResponse response = client.bulk(request, RequestOptions.DEFAULT); //3.輸出返回結果 System.out.println(response); } }