Elasticsearch安裝、入門、基礎API操作、全文檢索、精準查詢、地理查詢、復合查詢、排序、分頁、高亮、數據聚合、自動補全、數據同步、ES集群

學習資料:

通過網盤分享的文件:Elasticsearch
鏈接: https://pan.baidu.com/s/18BxA0BH0G–jwy95uFmFZQ 提取碼: yyds

初識ES

在這里插入圖片描述

在這里插入圖片描述

在這里插入圖片描述

正向索引

在這里插入圖片描述

倒排索引

在這里插入圖片描述

在這里插入圖片描述

ES與MySQL 概念對比

在這里插入圖片描述

在這里插入圖片描述

在這里插入圖片描述

在這里插入圖片描述

在這里插入圖片描述

安裝ES

在這里插入圖片描述

在這里插入圖片描述

在這里插入圖片描述

操作索引庫

在這里插入圖片描述

mapping屬性

在這里插入圖片描述

在這里插入圖片描述

創建索引庫

在這里插入圖片描述

{"mappings": {"properties": {"age": {"type": "integer"},"weight": {"type": "float"},"isMarried": {"type": "boolean"},"info": {"type": "text","analyzer": "standard"},"email": {"type": "keyword"},"score": {"type": "float"},"name": {"properties": {"firstName": {"type": "text","analyzer": "standard"},"lastName": {"type": "text","analyzer": "standard"}}}}}
}

請求es


PUT http://localhost:9200/user_info
Content-Type: application/json{"mappings": {"properties": {"age": {"type": "integer"},"weight": {"type": "float"},"isMarried": {"type": "boolean"},"info": {"type": "text","analyzer": "standard"},"email": {"type": "keyword"},"score": {"type": "float"},"name": {"properties": {"firstName": {"type": "text","analyzer": "standard"},"lastName": {"type": "text","analyzer": "standard"}}}}}
}

查看、刪除索引庫

在這里插入圖片描述

修改索引庫

在這里插入圖片描述

在這里插入圖片描述

操作文檔

添加文檔

在這里插入圖片描述

查看、刪除文檔

在這里插入圖片描述

修改文檔

在這里插入圖片描述

在這里插入圖片描述

RestClient 操作索引庫

在這里插入圖片描述

在這里插入圖片描述

在這里插入圖片描述

初始化 RestClient

在這里插入圖片描述

<properties><java.version>1.8</java.version><elasticsearch.version>7.12.1</elasticsearch.version>
</properties>
<dependency><groupId>org.elasticsearch.client</groupId><artifactId>elasticsearch-rest-high-level-client</artifactId>
</dependency>

public class HotelConstants {public static final String MAPPING_TEMPLATE = "{\n" +"  \"mappings\": {\n" +"    \"properties\": {\n" +"      \"id\": {\n" +"        \"type\": \"keyword\"\n" +"      },\n" +"      \"name\":{\n" +"        \"type\": \"text\",\n" +"        \"analyzer\": \"ik_max_word\",\n" +"        \"copy_to\": \"all\"\n" +"      },\n" +"      \"address\":{\n" +"        \"type\": \"keyword\",\n" +"        \"index\": false\n" +"      },\n" +"      \"price\":{\n" +"        \"type\": \"integer\"\n" +"      },\n" +"      \"score\":{\n" +"        \"type\": \"integer\"\n" +"      },\n" +"      \"brand\":{\n" +"        \"type\": \"keyword\",\n" +"        \"copy_to\": \"all\"\n" +"      },\n" +"      \"city\":{\n" +"        \"type\": \"keyword\",\n" +"        \"copy_to\": \"all\"\n" +"      },\n" +"      \"starName\":{\n" +"        \"type\": \"keyword\"\n" +"      },\n" +"      \"business\":{\n" +"        \"type\": \"keyword\"\n" +"      },\n" +"      \"location\":{\n" +"        \"type\": \"geo_point\"\n" +"      },\n" +"      \"pic\":{\n" +"        \"type\": \"keyword\",\n" +"        \"index\": false\n" +"      },\n" +"      \"all\":{\n" +"        \"type\": \"text\",\n" +"        \"analyzer\": \"ik_max_word\"\n" +"      }\n" +"    }\n" +"  }\n" +"}";
}

import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;import java.io.IOException;public class HotelIndexTest {private RestHighLevelClient client;@BeforeEachvoid setUp() {this.client = new RestHighLevelClient(RestClient.builder(HttpHost.create("http://192.168.150.101:9200")));}@AfterEachvoid tearDown() throws IOException {this.client.close();}@Testvoid testInit() {System.out.println(client);}}

創建索引庫

在這里插入圖片描述


@Test
void createHotelIndex() throws IOException {// 1.創建Request對象CreateIndexRequest request = new CreateIndexRequest("hotel");// 2.準備請求的參數:DSL語句request.source(MAPPING_TEMPLATE, XContentType.JSON);// 3.發送請求client.indices().create(request, RequestOptions.DEFAULT);
}

在這里插入圖片描述

刪除索引庫

刪除索引庫


@Test
void testDeleteHotelIndex() throws IOException {// 1.創建Request對象DeleteIndexRequest request = new DeleteIndexRequest("hotel");// 2.發送請求client.indices().delete(request, RequestOptions.DEFAULT);
}

判斷索引庫是否存在

判斷索引庫是否存在


@Test
void testExistsHotelIndex() throws IOException {// 1.創建Request對象GetIndexRequest request = new GetIndexRequest("hotel");// 2.發送請求boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);// 3.輸出System.err.println(exists ? "索引庫已經存在!" : "索引庫不存在!");
}

RestClient 操作文檔

初始化 RestClient

private IHotelService hotelService;private RestHighLevelClient client;@BeforeEach
void setUp() {this.client = new RestHighLevelClient (RestClient.builder (HttpHost.create ("http://192.168.111.101:9200")));
}@AfterEach
void tearDown() throws IOException {this.client.close ();
}

新增文檔

新增文檔

索引庫 實體類

數據庫查詢后的結果是一個Hotel類型的對象。數據庫結構如下:

@Data
@TableName("tb_hotel")
public class Hotel {@TableId(type = IdType.INPUT)private Long id;private String name;private String address;private Integer price;private Integer score;private String brand;private String city;private String starName;private String business;private String longitude;private String latitude;private String pic;
}

與我們的索引庫結構 存在差異

  • longitudelatitude需要合并為 location

因此,我們需要定義一個新的類型,與索引庫結構吻合:


import lombok.Data;
import lombok.NoArgsConstructor;@Data
@NoArgsConstructor
public class HotelDoc {private Long id;private String name;private String address;private Integer price;private Integer score;private String brand;private String city;private String starName;private String business;private String location;private String pic;public HotelDoc(Hotel hotel) {this.id = hotel.getId();this.name = hotel.getName();this.address = hotel.getAddress();this.price = hotel.getPrice();this.score = hotel.getScore();this.brand = hotel.getBrand();this.city = hotel.getCity();this.starName = hotel.getStarName();this.business = hotel.getBusiness();this.location = hotel.getLatitude() + ", " + hotel.getLongitude();this.pic = hotel.getPic();}
}

語法說明:

POST /{索引庫名}/_doc/1
{"name": "Jack","age": 21
}

在這里插入圖片描述

我們導入酒店數據,基本流程一致,但是需要考慮幾點變化:

  • 酒店數據來自于數據庫,我們需要 先查詢出來,得到hotel對象
  • hotel對象需要轉為 HotelDoc對象
  • HotelDoc需要序列化為 json格式

@Test
void testAddDocument() throws IOException {// 1.根據id查詢酒店數據Hotel hotel = hotelService.getById(61083L);// 2.轉換為文檔類型HotelDoc hotelDoc = new HotelDoc(hotel);// 3.將HotelDoc轉jsonString json = JSON.toJSONString(hotelDoc);// 1.準備Request對象IndexRequest request = new IndexRequest("hotel").id(hotelDoc.getId().toString());// 2.準備Json文檔request.source(json, XContentType.JSON);// 3.發送請求client.index(request, RequestOptions.DEFAULT);
}

查詢文檔

查詢文檔

在這里插入圖片描述


@Test
void testGetDocumentById() throws IOException {// 1.準備RequestGetRequest request = new GetRequest("hotel", "61083");// 2.發送請求,得到響應GetResponse response = client.get(request, RequestOptions.DEFAULT);// 3.解析響應結果String json = response.getSourceAsString();HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);System.out.println(hotelDoc);
}

刪除文檔

刪除文檔

@Test
void testDeleteDocument() throws IOException {// 1.準備RequestDeleteRequest request = new DeleteRequest("hotel", "61083");// 2.發送請求client.delete(request, RequestOptions.DEFAULT);
}

修改文檔

修改文檔

在這里插入圖片描述


@Test
void testUpdateDocument() throws IOException {// 1.準備RequestUpdateRequest request = new UpdateRequest("hotel", "61083");// 2.準備請求參數request.doc("price", "952","starName", "四鉆");// 3.發送請求client.update(request, RequestOptions.DEFAULT);
}

批量導入文檔

批量導入文檔

批量處理BulkRequest,其本質就是 將多個普通的CRUD請求組合在一起發送。

在這里插入圖片描述

其中提供了一個add方法,用來添加其他請求:
在這里插入圖片描述

可以看到,能添加的請求包括:

  • IndexRequest,也就是新增
  • UpdateRequest,也就是修改
  • DeleteRequest,也就是刪除
    因此Bulk中添加了多個IndexRequest,就是批量新增功能了。示例:
    在這里插入圖片描述

@Test
void testBulkRequest() throws IOException {// 批量查詢酒店數據List<Hotel> hotels = hotelService.list();// 1.創建RequestBulkRequest request = new BulkRequest();// 2.準備參數,添加多個新增的Requestfor (Hotel hotel : hotels) {// 2.1.轉換為文檔類型HotelDocHotelDoc hotelDoc = new HotelDoc(hotel);// 2.2.創建新增文檔的Request對象request.add(new IndexRequest("hotel").id(hotelDoc.getId().toString()).source(JSON.toJSONString(hotelDoc), XContentType.JSON));}// 3.發送請求client.bulk(request, RequestOptions.DEFAULT);
}

DSL 查詢分類

在這里插入圖片描述

查詢語法基本一致

GET /indexName/_search
{"query": {"查詢類型": {"查詢條件": "條件值"}}
}

我們以查詢所有為例,其中:

  • 查詢類型為 match_all
  • 沒有查詢條件

// 查詢所有
GET /indexName/_search
{"query": {"match_all": {}}
}

其它查詢無非就是 查詢類型、查詢條件 的變化

全文檢索

在這里插入圖片描述

使用場景

全文檢索查詢 的基本流程如下:

  • 對 用戶 搜索的內容做分詞,得到詞條
  • 根據 詞條去倒排索引庫中匹配,得到文檔id
  • 根據 文檔id找到文檔,返回給用戶

比較常用的場景包括:

  • 商城的輸入框搜索
  • 百度輸入框搜索

因為是 拿著詞條去匹配,因此參與搜索的字段也必須是 可分詞的text類型的字段

基本語法
常見的全文檢索查詢包括:

  • match查詢:單字段查詢
  • multi_match查詢:多字段查詢,任意一個字段符合條件就算 符合查詢條件

match 查詢語法如下:

GET /hotel/_search
{"query": {"match": {"brand": "7天酒店"}}
}

mulit_match 語法如下:

GET /indexName/_search
{"query": {"multi_match": {"query": "TEXT","fields": ["FIELD1", " FIELD12"]}}
}

我們將brand、name、business值都利用copy_to復制到了all字段中。因此你根據三個字段搜索,和根據all字段搜索效果當然一樣

但是,搜索字段越多,對查詢性能影響越大,因此建議采用copy_to,然后 單字段查詢的方式
總結

match和multi_match的區別是什么?

  • match:根據一個字段查詢
  • multi_match:根據多個字段查詢,參與查詢字段越多,查詢性能越差

精準查詢

在這里插入圖片描述
精確查詢一般是 查找keyword、數值、日期、boolean等類型字段。所以不會對搜索條件分詞。常見的有:

  • term:根據 詞條精確值查詢
  • range:根據 值的范圍查詢

term 查詢

// term查詢
GET /hotel/_search
{"query": {"term": {"brand":"7天酒店"}}
}

range 查詢

GET /hotel/_search
{"query": {"range": {"price": {"gte": 100,"lte": 200}}}
}

總結

精確查詢常見的有哪些?

  • term 查詢:根據 詞條精確匹配,一般 搜索keyword類型、數值類型、布爾類型、日期類型字段
  • range查詢:根據 數值范圍查詢,可以是 數值、日期的范圍

地理坐標查詢

在這里插入圖片描述

附近查詢

在這里插入圖片描述

GET /hotel/_search
{"query": {"geo_distance":{"distance":"15km", "location":"31.21,121.5" }}
}

復合查詢

在這里插入圖片描述
復合(compound)查詢:復合查詢可以 將其它簡單查詢組合起來,實現更復雜的搜索邏輯。常見的有兩種:

  • fuction score算分函數查詢,可以 控制文檔相關性算分,控制文檔排名
  • bool query布爾查詢, 利用 邏輯關系組合多個其它的查詢,實現復雜搜索
    算分函數查詢
    利用match查詢時,文檔結果會根據與搜索詞條的關聯度打分(_score),返回結果時 按照分值降序排列

例如,我們搜索 “虹橋如家”,結果如下:


[{"_score" : 17.850193,"_source" : {"name" : "虹橋如家酒店真不錯",}},{"_score" : 12.259849,"_source" : {"name" : "外灘如家酒店真不錯",}},{"_score" : 11.91091,"_source" : {"name" : "迪士尼如家酒店真不錯",}}
]

語法說明
在這里插入圖片描述

function score的運行流程如下:

  • 1)根據原始條件查詢搜索文檔,并且計算相關性算分,稱為原始算分(query score)
  • 2)根據過濾條件,過濾文檔
  • 3)符合過濾條件的文檔,基于算分函數運算,得到函數算分(function score)
  • 4)將原始算分(query score)和函數算分(function score)基于運算模式做運算,得到最終結果,作為相關性算分。

GET /hotel/_search
{"query": {"function_score": {"query": {"match": {"all": "外灘"}},"functions": [{"filter": {"range": {"price": {"gte": 100,"lte": 300}}},"weight": 10}],"boost_mode": "avg"}}
}

在這里插入圖片描述

布爾查詢
布爾查詢 是一個或多個查詢子句的組合,每一個子句就是一個子查詢。子查詢的組合方式有:

  • must:必須匹配每個子查詢,類似 “與”
  • should:選擇性匹配子查詢,類似 “或”
  • must_not:必須不匹配,不參與算分,類似 “非”
  • filter:必須匹配,不參與算分

GET /hotel/_search
{"query": {"bool": {"must": [{"term": {"city": "上海" }}],"should": [{"term": {"brand": "皇冠假日" }},{"term": {"brand": "華美達" }}],"must_not": [{ "range": { "price": { "lte": 500 } }}],"filter": [{ "range": {"score": { "gte": 45 } }}]}}
}

排序

在這里插入圖片描述
單字段 排序

排序 字段、排序方式 ASC、DESC


GET /hotel/_search
{"query": {"match_all": {}},"sort": [{"price": "desc"  }]
}

多字段 排序

按照 用戶評價(score ) 降序排序,評價 相同的按照價格 ( price) 升序排序


GET /hotel/_search
{"query": {"match_all": {}},"sort": [{"score": "desc"},{"price": "asc"}]
}

地理坐標排序

  • unit:排序的距離單位
  • location:目標坐標點

GET /hotel/_search
{"query": {"match_all": {}},"sort": [{"_geo_distance" : {"location": "31.21,121.5", "order" : "asc","unit" : "km" }}]
}

這個查詢的含義是:

  • 指定 一個坐標,作為目標點
  • 計算 每一個文檔中,指定字段(必須是geo_point類型)的坐標 到 目標點的距離是多少
  • 根據距離 升序排序

分頁

在這里插入圖片描述

GET /hotel/_search
{"query": {"match_all": {}},"from": 0, // 分頁開始的位置,默認為0"size": 10, // 期望獲取的文檔總數"sort": [{"price": "asc"}]
}

深度分頁:

  • search after:分頁時 需要排序,原理是從上一次的排序值開始,查詢下一頁數據。官方推薦使用的方式

高亮

什么是高亮顯示呢?

我們在百度,京東搜索時,關鍵字會變成紅色,比較醒目,這叫高亮顯示:
在這里插入圖片描述

在這里插入圖片描述
高亮顯示的實現分為兩步:

  • 1)給 文檔中的所有關鍵字都添加一個標簽,例如<em>標簽
  • 2)頁面給<em>標簽 編寫CSS樣式
GET /hotel/_search
{"query": {"match": {"FIELD": "TEXT" // 查詢條件,高亮一定要使用全文檢索查詢}},"highlight": {"fields": { // 指定要高亮的字段"FIELD": {"pre_tags": "<em>",  // 用來標記高亮字段的前置標簽"post_tags": "</em>" // 用來標記高亮字段的后置標簽}}}
}

實現高亮

在這里插入圖片描述

GET /hotel/_search
{"query": {"match": {"all": "如家"}},"highlight": {"fields": {"name": {"require_field_match": "false"}}}
}

注意:

  • 高亮是對關鍵字高亮,因此搜索條件必須帶有關鍵字,而不能是范圍這樣的查詢。
  • 默認情況下,高亮的字段,必須與搜索指定的字段一致,否則無法高亮
  • 如果要對非搜索字段高亮,則需要添加一個屬性:required_field_match=false

GET /hotel/_search
{"query": {"match": {"all": "如家酒店"}},"from": 0, "size": 20, "sort": [{"price": "asc"},{"_geo_distance": {"location": "31.21,121.5","order": "asc","unit": "km"}}], "highlight": {"fields": {"name": {"require_field_match": "false"}}}
}

數據聚合

GET /hotel/_search
{"size": 0,   // 設置size為0,結果中  不包含文檔,只包含聚合結果~"aggs": {    // 定義聚合"brandAgg": {  //給聚合起個名字"terms": {   // 聚合的類型,按照品牌值聚合,所以選擇term"field": "brand",   // 參與聚合的字段"size": 20    // 希望獲取的聚合結果數量}}}
}

在這里插入圖片描述
聚合結果排序
默認情況下,Bucket聚合會統計Bucket內的文檔數量,記為_count,并且按照_count降序排序。

我們可以指定order屬性,自定義聚合的排序方式:


GET /hotel/_search
{"size": 0, "aggs": {"brandAgg": {"terms": {"field": "brand","order": {"_count": "asc" // 按照_count升序排列},"size": 20}}}
}

限定聚合范圍
可以限定要聚合的文檔范圍,只要添加query條件即可

GET /hotel/_search
{"query": {"range": {"price": {"lte": 200 // 只對200元以下的文檔聚合}}}, "size": 0, "aggs": {"brandAgg": {"terms": {"field": "brand","size": 20}}}
}

在這里插入圖片描述

Metric聚合語法
對酒店按照品牌分組,形成了一個個桶。現在我們需要對桶內的酒店做運算,獲取每個品牌的用戶評分的min、max、avg等值。

這就要用到Metric聚合了,例如stat聚合:就可以獲取min、max、avg等結果。

語法如下:

GET /hotel/_search
{"size": 0, "aggs": {"brandAgg": { "terms": { "field": "brand", "size": 20},"aggs": { // 是brands聚合的子聚合,也就是 分組后對每組分別計算"score_stats": { // 聚合名稱"stats": { // 聚合類型,這里stats可以計算min、max、avg等"field": "score" // 聚合字段,這里是score}}}}}
}

在這里插入圖片描述

數據同步

在這里插入圖片描述

在這里插入圖片描述

在這里插入圖片描述

在這里插入圖片描述

在這里插入圖片描述

使用MQ 完成數據同步

在這里插入圖片描述

在這里插入圖片描述

在這里插入圖片描述

在這里插入圖片描述

流程如下:

  • hotel-admin對mysql數據庫數據完成增、刪、改后,發送MQ消息
  • hotel-demo監聽MQ,接收到消息后完成elasticsearch數據修改

<!--amqp-->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId>
</dependency>

package cn.itcast.hotel.constatnts;public class MqConstants {/*** 交換機*/public final static String HOTEL_EXCHANGE = "hotel.topic";/*** 監聽新增和修改的隊列*/public final static String HOTEL_INSERT_QUEUE = "hotel.insert.queue";/*** 監聽刪除的隊列*/public final static String HOTEL_DELETE_QUEUE = "hotel.delete.queue";/*** 新增或修改的RoutingKey*/public final static String HOTEL_INSERT_KEY = "hotel.insert";/*** 刪除的RoutingKey*/public final static String HOTEL_DELETE_KEY = "hotel.delete";
}

package cn.itcast.hotel.config;import cn.itcast.hotel.constants.MqConstants;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class MqConfig {@Beanpublic TopicExchange topicExchange(){return new TopicExchange(MqConstants.HOTEL_EXCHANGE, true, false);}@Beanpublic Queue insertQueue(){return new Queue(MqConstants.HOTEL_INSERT_QUEUE, true);}@Beanpublic Queue deleteQueue(){return new Queue(MqConstants.HOTEL_DELETE_QUEUE, true);}@Beanpublic Binding insertQueueBinding(){return BindingBuilder.bind(insertQueue()).to(topicExchange()).with(MqConstants.HOTEL_INSERT_KEY);}@Beanpublic Binding deleteQueueBinding(){return BindingBuilder.bind(deleteQueue()).to(topicExchange()).with(MqConstants.HOTEL_DELETE_KEY);}
}

發送MQ 消息

在這里插入圖片描述

接收MQ 消息


void deleteById(Long id);void insertById(Long id);

@Override
public void deleteById(Long id) {try {// 1.準備RequestDeleteRequest request = new DeleteRequest("hotel", id.toString());// 2.發送請求client.delete(request, RequestOptions.DEFAULT);} catch (IOException e) {throw new RuntimeException(e);}
}@Override
public void insertById(Long id) {try {// 0.根據id查詢酒店數據Hotel hotel = getById(id);// 轉換為文檔類型HotelDoc hotelDoc = new HotelDoc(hotel);// 1.準備Request對象IndexRequest request = new IndexRequest("hotel").id(hotel.getId().toString());// 2.準備Json文檔request.source(JSON.toJSONString(hotelDoc), XContentType.JSON);// 3.發送請求client.index(request, RequestOptions.DEFAULT);} catch (IOException e) {throw new RuntimeException(e);}
}

package cn.itcast.hotel.mq;import cn.itcast.hotel.constants.MqConstants;
import cn.itcast.hotel.service.IHotelService;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;@Component
public class HotelListener {@Autowiredprivate IHotelService hotelService;/*** 監聽酒店新增或修改的業務* @param id 酒店id*/@RabbitListener(queues = MqConstants.HOTEL_INSERT_QUEUE)public void listenHotelInsertOrUpdate(Long id){hotelService.insertById(id);}/*** 監聽酒店刪除的業務* @param id 酒店id*/@RabbitListener(queues = MqConstants.HOTEL_DELETE_QUEUE)public void listenHotelDelete(Long id){hotelService.deleteById(id);}
}

ES 集群

在這里插入圖片描述

在這里插入圖片描述

在這里插入圖片描述

RestClient查詢文檔

發起查詢請求

在這里插入圖片描述
這里關鍵的API有兩個,一個是request.source(),其中包含了查詢、排序、分頁、高亮等所有功能:
在這里插入圖片描述
另一個是QueryBuilders,其中包含match、term、function_score、bool等各種查詢:
在這里插入圖片描述

解析響應

一層一層地解析

在這里插入圖片描述
Elasticsearch返回的結果是一個 JSON字符串,結構包含:

  • hits:命中的結果
    • total:總條數,其中的value是具體的總條數值
    • max_score:所有結果中得分最高的文檔的相關性算分
    • hits:搜索結果的文檔數組,其中的每個文檔都是一個json對象
      • _source:文檔中的原始數據,也是json對象

因此,我們解析響應結果,就是逐層解析JSON字符串,流程如下:

  • SearchHits:通過response.getHits()獲取,就是JSON中的最外層的hits,代表命中的結果
    • SearchHits#getTotalHits().value:獲取總條數信息
    • SearchHits#getHits():獲取SearchHit數組,也就是文檔數組
      • SearchHit#getSourceAsString():獲取文檔結果中的_source,也就是原始的json文檔數據
@Test
void testMatchAll() throws IOException {// 1.準備RequestSearchRequest request = new SearchRequest("hotel");// 2.準備DSLrequest.source().query(QueryBuilders.matchAllQuery());// 3.發送請求SearchResponse response = client.search(request, RequestOptions.DEFAULT);// 4.解析響應handleResponse(response);
}private void handleResponse(SearchResponse response) {// 4.解析響應SearchHits searchHits = response.getHits();// 4.1.獲取總條數long total = searchHits.getTotalHits().value;System.out.println("共搜索到" + total + "條數據");// 4.2.文檔數組SearchHit[] hits = searchHits.getHits();// 4.3.遍歷for (SearchHit hit : hits) {// 獲取文檔sourceString json = hit.getSourceAsString();// 反序列化HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);System.out.println("hotelDoc = " + hotelDoc);}
}

match查詢

@Test
void testMatch() throws IOException {// 1.準備RequestSearchRequest request = new SearchRequest("hotel");// 2.準備DSLrequest.source().query(QueryBuilders.matchQuery("all", "如家"));// 3.發送請求SearchResponse response = client.search(request, RequestOptions.DEFAULT);// 4.解析響應handleResponse(response);}

精確查詢

精確查詢主要是兩者:

  • term:詞條精確匹配
  • range:范圍查詢

與之前的查詢相比,差異同樣在查詢條件,其它都一樣。

查詢條件構造的API如下:
在這里插入圖片描述

布爾查詢

@Test
void testBool() throws IOException {// 1.準備RequestSearchRequest request = new SearchRequest("hotel");// 2.準備DSL// 2.1.準備BooleanQueryBoolQueryBuilder boolQuery = QueryBuilders.boolQuery();// 2.2.添加termboolQuery.must(QueryBuilders.termQuery("city", "杭州"));// 2.3.添加rangeboolQuery.filter(QueryBuilders.rangeQuery("price").lte(250));request.source().query(boolQuery);// 3.發送請求SearchResponse response = client.search(request, RequestOptions.DEFAULT);// 4.解析響應handleResponse(response);}

排序、分頁

排序和分頁是與query同級的參數,因此同樣是使用 request.source() 來設置。
在這里插入圖片描述

@Test
void testPageAndSort() throws IOException {// 頁碼,每頁大小int page = 1, size = 5;// 1.準備RequestSearchRequest request = new SearchRequest("hotel");// 2.準備DSL// 2.1.queryrequest.source().query(QueryBuilders.matchAllQuery());// 2.2.排序 sortrequest.source().sort("price", SortOrder.ASCENDING);// 2.3.分頁 from、sizerequest.source().from((page - 1) * size).size(5);// 3.發送請求SearchResponse response = client.search(request, RequestOptions.DEFAULT);// 4.解析響應handleResponse(response);}

距離排序

在這里插入圖片描述

if (location != null && !location.equals ("")) {request.source ().sort (SortBuilders.geoDistanceSort ("location", new GeoPoint (location)).order (SortOrder.ASCENDING).unit (DistanceUnit.KILOMETERS));
}

高亮

高亮請求構建

  • 查詢的DSL:其中除了查詢條件,還需要添加高亮條件,同樣是與query同級。
  • 結果解析:結果除了要解析 _source 文檔數據,還要解析高亮結果
    在這里插入圖片描述
@Test
void testHighlight() throws IOException {// 1.準備RequestSearchRequest request = new SearchRequest ("hotel");// 2.準備DSL// 2.1.queryrequest.source ().query (QueryBuilders.matchQuery ("all", "如家"));// 2.2.高亮request.source ().highlighter (new HighlightBuilder ().field ("name").requireFieldMatch (false));// 3.發送請求SearchResponse response = client.search (request, RequestOptions.DEFAULT);// 4.解析響應handleResponse (response);}

高亮結果解析

在這里插入圖片描述

private void handleResponse(SearchResponse response) {// 4.解析響應SearchHits searchHits = response.getHits();// 4.1.獲取總條數long total = searchHits.getTotalHits().value;System.out.println("共搜索到" + total + "條數據");// 4.2.文檔數組SearchHit[] hits = searchHits.getHits();// 4.3.遍歷for (SearchHit hit : hits) {// 獲取文檔sourceString json = hit.getSourceAsString();// 反序列化HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);// 獲取高亮結果Map<String, HighlightField> highlightFields = hit.getHighlightFields();if (!CollectionUtils.isEmpty(highlightFields)) {// 根據字段名獲取高亮結果HighlightField highlightField = highlightFields.get("name");if (highlightField != null) {// 獲取高亮值String name = highlightField.getFragments()[0].string();// 覆蓋非高亮結果hotelDoc.setName(name);}}System.out.println("hotelDoc = " + hotelDoc);}
}

算分查詢

在這里插入圖片描述

// 算分控制
FunctionScoreQueryBuilder functionScoreQuery =QueryBuilders.functionScoreQuery(// 原始查詢,相關性算分的查詢boolQuery,// function score的數組new FunctionScoreQueryBuilder.FilterFunctionBuilder[]{// 其中的一個function score 元素new FunctionScoreQueryBuilder.FilterFunctionBuilder(// 過濾條件QueryBuilders.termQuery("isAD", true),// 算分函數ScoreFunctionBuilders.weightFactorFunction(10))});
request.source().query(functionScoreQuery);

RestAPI實現聚合

聚合條件與query條件同級別,因此需要使用request.source()來指定聚合條件。
在這里插入圖片描述
聚合的結果也與查詢結果不同,API也比較特殊。不過同樣是 JSON逐層解析:
在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/90966.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/90966.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/90966.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

教程:如何查看瀏覽器擴展程序的源碼

在學習前端、自動化或擴展開發時&#xff0c;我們常常會想研究某個瀏覽器插件的實現邏輯。即使擴展沒有公開源碼&#xff0c;只要我們本地安裝了它&#xff0c;就可以查看它的完整源代碼進行學習。? 方法一&#xff1a;從瀏覽器插件目錄提取源碼 第一步&#xff1a;打開擴展程…

虛擬儲能與分布式光伏協同優化:新型電力系統的靈活性解決方案

安科瑞顧強摘要&#xff1a; 在全球能源結構向低碳化、智能化加速轉型的背景下&#xff0c;分布式光伏的大規模接入為電力系統帶來機遇的同時&#xff0c;也因其波動性與間歇性帶來了運行挑戰。本文聚焦于虛擬儲能系統&#xff08;Virtual Energy Storage System, VESS&#xf…

java valueOf方法

一,什么是valueOf方法?valueOf是java包裝類(比如Long,Integer等)中提供的一個靜態方法二,valueOf的主要作用是什么主要作用是將其他類型的數據轉換為當前包裝類的對象三,代碼實例:咱們以Long.valueOf為例,1,他可以接受一個long類型的數值,返回對應的Long對象(把基本類型long包…

工業平板電腦 vs 消費級平板:從防護等級到使用壽命全方面對比

平板電腦已經廣泛應用于各個行業。但你知道嗎&#xff1f;市面上常見的“平板”其實可以分為兩大類&#xff1a;工業平板電腦和消費級平板電腦。雖然它們看起來都是“平板”&#xff0c;但用途、性能和適用場景卻大不相同。今天&#xff0c;我們就來聊聊這兩者的區別&#xff0…

MySQL技術筆記-索引+慢 SQL+鎖 全鏈路優化實戰

目錄 前言 MySQL索引 一、概述 二、索引分類 &#xff08;一&#xff09;按功能特性分類 &#xff08;二&#xff09;按存儲方式分類 &#xff08;三&#xff09;按數據結構分類 &#xff08;四&#xff09;按索引字段數量分類 三、索引的優缺點 &#xff08;一&…

S7-1200 與 S7-300 PNS7-400 PN UDP 通信 TIA 相同項目

7-1200 與 S7-300 PN/S7-400 PN UDP 通信 TIA 相同項目S7-1200 與 S7-300 PN 口之間的以太網通信可以通過 UDP 協議來實現&#xff0c;使用的通信指令是在雙方 CPU 調用通信-開放式用戶通信TSEND_C&#xff0c;TRCV_C&#xff08;1200支持&#xff0c;300不支持&#xff09;或T…

java進階(二)+學習筆記

面向對象設計原則1. 面向對象概念面向對象 是一種編程思想&#xff0c;面向過程是關注實現的步驟&#xff0c;每個步驟定義一個函數&#xff0c;調用函數執行即可。面向對象關注的是誰(對象)來執行&#xff0c; 把具有相同屬性和行為的一類事物(對象)進行抽象成類&#…

[附源碼+數據庫+畢業論]基于Spring Boot+mysql+vue結合內容推薦算法的學生咨詢系統

摘要 隨著互聯網的普及&#xff0c;學生在學習和生活中面臨著海量信息&#xff0c;如何高效獲取有價值的內容成為亟待解決的問題。本文基于 Spring Boot 框架&#xff0c;結合內容推薦算法&#xff0c;設計并實現了一個學生咨詢系統。系統采用 Spring Boot MyBatis MySQL Vu…

DeepSeek 微調實踐:DeepSeek-R1 大模型基于 MS-Swift 框架部署 / 推理 / 微調實踐大全

注&#xff1a;此文章內容均節選自充電了么創始人&#xff0c;CEO兼CTO陳敬雷老師的新書《GPT多模態大模型與AI Agent智能體》&#xff08;跟我一起學人工智能&#xff09;【陳敬雷編著】【清華大學出版社】 GPT多模態大模型與AI Agent智能體書籍本章配套視頻課程【陳敬雷】 文…

python基礎知識pip配置pip.conf文件

pip.conf一、 INI格式二、 級別三、 文件位置四、 加載順序五、 常用一、 INI格式 配置文件可以更改pip命令行選項的默認值&#xff0c;這個文件是使用INI格式編寫的。 INI格式 主要包含三個內容&#xff1a;1.節section 2.鍵值對 3.注釋 [section1] key1 value1 \\注釋 key2…

深入理解 Java JVM

文章目錄&#x1f4d5;1. JVM簡介&#x1f4d5;2. JVM運行流程&#x1f4d5;3. JVM運行時數據區&#x1f4d5;4. JVM類加載??4.1 類加載過程??4.2 雙親委派模型??4.3 破壞雙親委派模型&#x1f4d5;5. JVM垃圾回收機制&#xff08;GC機制&#xff09;??5.1 判斷死亡對象…

Linux內核高效之道:Slab分配器與task_struct緩存管理

前言 在Linux內核中&#xff0c;進程創建與銷毀是最頻繁的操作之一。想象一下&#xff1a;當系統每秒需要處理成百上千次fork()和exit()調用時&#xff0c;如何保證task_struct&#xff08;進程描述符&#xff09;的分配與釋放既快速又不產生內存碎片&#xff1f;這就是Slab分配…

雙esp8266-01之間UDP透傳傳輸,自定義協議

使用AT模式的透傳&#xff0c;串口打印的數據包含pd1,4,數據打印的數據不是直接將數據打印出來&#xff0c;包含了pd1,4,特殊字符&#xff0c;針對想要直接開機直接透傳&#xff0c;打印數據且按照自主協議幀頭的功能進行開發。1.server程序&#xff1a;/*************SERVER**…

BGP 路由優選屬性(7)【MED】官方考試綜合實驗題【bgp】【acl】【ip-prefix】【route-policy】【icmp 環路】精講

目錄 一、MED 屬性介紹 二、實驗 2.1 實驗目的 2.2 拓撲圖 2.2 實驗說明 2.3 配置腳本 2.4 驗證配置 2.5 問題分析 2.7 題目需求解析 2.8 場景 1&#xff1a;只允許在 AS12 上操作 2.9 場景 2&#xff1a;只允許在 AS34 上操作 正文 一、MED 屬性介紹 MED 全稱 mu…

html-初級標簽

一.瀏覽器能識別的標簽 1.1 head標簽里的編碼和title <head><meta charset"UTF-8"><title>Title</title> </head>1.2 標題 <body><h1>Welcome to my website</h1><h2>Welcome to my website</h2><…

【八股消消樂】Kafka集群 full GC 解決方案

&#x1f60a;你好&#xff0c;我是小航&#xff0c;一個正在變禿、變強的文藝傾年。 &#x1f514;本專欄《八股消消樂》旨在記錄個人所背的八股文&#xff0c;包括Java/Go開發、Vue開發、系統架構、大模型開發、具身智能、機器學習、深度學習、力扣算法等相關知識點&#xff…

《Java Web程序設計》實驗報告二 學習使用HTML標簽、表格、表單

目 錄 一、實驗目的 二、實驗環境 三、實驗步驟和內容 1、小組成員分工&#xff08;共計4人&#xff09; 2、實驗方案 3、實驗結果與分析 4、項目任務評價 四、遇到的問題和解決方法 五、實驗總結 一、實驗目的 1、HTML基礎知識、基本概念 2、使用HTML標簽、表格進行…

jenkins使用Jenkinsfile部署springboot+docker項目

文章目錄前言一、前期準備二、編輯構建文件二、Jenkins構建總結前言 前面使用Jenkinsfile部署了前端vue項目&#xff0c;接著學習Jenkinsfile部署springboot項目。 一、前期準備 已經安裝好centos,并且安裝了jenkins和docker。本地新建springboot并上傳到gitee上。 二、編輯…

使用ESM3蛋白質語言模型進行快速大規模結構預測

文章目錄ESM3介紹ESM3在線使用本地使用api批量預測ESM相較于AlphaFold的優勢ESM3介紹 ESM3是由EvolutionaryScale&#xff08;前Meta團隊&#xff09;開發的一款蛋白質大語言模型&#xff0c;于2025年以《用語言模型模擬 5 億年的進化》為題正式發表在Science上 文章鏈接: htt…

PostgreSQL 時間/日期管理詳解

PostgreSQL 時間/日期管理詳解 引言 PostgreSQL是一款功能強大的開源關系型數據庫管理系統&#xff0c;在時間/日期管理方面具有獨特的優勢。本文將詳細介紹PostgreSQL中時間/日期數據類型及其相關功能&#xff0c;幫助讀者更好地理解和應用時間/日期管理。 時間/日期數據類型 …