一、RestClient操作索引库
什么是RestClient?
ES官方提供了各种不同语言的客户端,用来操作ES。这些客户端的本质就是组装DSL语句
,通过http请求
发送给ES。官方文档地址: https://www.elastic.co/guide/en/elasticsearch/client/index.html
案例:利用 JavaRestClient 实现创建、删除索引库,判断索引库是否存在
根据课前资料提供的酒店数据创建索引库,索引库名为hotel
,mapping属性根据数据库结构定义。
准备步骤如下:
- 导入课前资料Demo
- 分析数据结构,定义mapping属性
小提示 - ES中支持两种地理坐标数据类型:
- geo_point:由纬度(latitude) 和经度(longitude)确定的
一个点
。例如:“32.8752345, 120.2981576” - geo_shape:有多个geo_point组成的
复杂几何图形
。例如一条直线,“LINESTRING (-77.03653 38.897676, -77.009051 38.889939)”
- 字段拷贝可以使用
copy_to
属性将当前字段拷贝到指定字段。示例:
"all": {
"type": "text",
"analyzer": "ik_max_word"
},
"brand": {
"type": "keyword",
"copy_to": "all"
}
3. 初始化JavaRestClient
实际步骤
1.引入es的RestHighLevelClient
依赖:
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
</dependency>
- 因为SpringBoot默认的ES版本是7.6.2,所以我们需要覆盖默认的ES版本:
<properties>
<java.version>1.8</java.version>
<elasticsearch.version>7.12.1</elasticsearch.version>
</properties>
- 初始化RestHighLevelClient:
RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(
HttpHost.create("http://192.168.150.101:9200")
));
4. 利用JavaRestClient创建索引库
5. 利用JavaRestClient删除索引库
@Test
void testDeleteIndex() throws IOException {
// 1.准备Request
DeleteIndexRequest request = new DeleteIndexRequest("hotel");
// 2.发送请求
client.indices().delete(request, RequestOptions.DEFAULT);
}
6.利用JavaRestClient判断索引库是否存在
@Test
void testExistsIndex() throws IOException {
// 1.准备Request
GetIndexRequest request = new GetIndexRequest("hotel");
// 2.发送请求
boolean isExists = client.indices().exists(request, RequestOptions.DEFAULT);
System.out.println(isExists ? "存在" : "不存在");
}
二、RestClient操作文档
案例1:利用JavaRestClient实现文档的CRUD
去数据库查询酒店数据,导入到hotel索引库,实现酒店数据的CRUD。
基本步骤如下:
初始化JavaRestClient
利用JavaRestClient
新增酒店数据
3. 利用JavaRestClient
根据id查询酒店数据
利用JavaRestClient
删除酒店数据
@Test
void testDeleteDocumentById() throws IOException {
// 1.准备Request // DELETE /hotel/_doc/{id}
DeleteRequest request = new DeleteRequest("hotel", "61083");
// 2.发送请求
client.delete(request, RequestOptions.DEFAULT);
}
- 利用JavaRestClient
修改酒店数据
案例2:利用JavaRestClient批量导入酒店数据到ES
需求:批量查询酒店数据,然后批量导入索引库中
思路:
- 利用mybatis-plus查询酒店数据
- 将查询到的酒店数据(Hotel) 转换为文档类型数据(HotelDoc)
- 利用JavaRestClient中 的Bulk批处理,实现批量新增文档,示例代码如下
@Test
void testBulkRequest() throws IOException {
// 查询所有的酒店数据
List<Hotel> list = hotelService.list();
// 1.准备Request
BulkRequest request = new BulkRequest();
// 2.准备参数
for (Hotel hotel : list) {
// 2.1.转为HotelDoc
HotelDoc hotelDoc = new HotelDoc(hotel);
// 2.2.转json
String json = JSON.toJSONString(hotelDoc);
// 2.3.添加请求
request.add(new IndexRequest("hotel").id(hotel.getId().toString()).source(json, XContentType.JSON));
}
// 3.发送请求
client.bulk(request, RequestOptions.DEFAULT);
}
三、DSL查询
查询语法
GET /hotel/_search
{
"query": {
"match_all": {}
},
"from": 10, #默认0
"size": 20, #默认10
"sort": {
"price": "asc"
},
"highlight": {
"fields": {
"name": {
"require_field_match": "false",
"pre_tags": "<en>",
"post_tags": "</en>"
}
}
},
"aggs": {
"brandAgg":{
"terms": {
"field": "brand",
"order": {
"_count": "asc"
},
"size": 20
}
}
}
}
DSL Query的分类
查询基本语法如下:
Elasticsearch提供了基于JSON的DSL (Domain Specific Language)来定义查询。常见的查询类型包括:
查询所有:查询出所有数据,一般测试用。例如:
match_all
全文检索(full text)查询:利用分词器对用户输入内容分词,然后去倒排索引库中匹配。例如:
match_query
multi_match_query
精确查询:根据精确词条值查找数据,一般是查找
keyword、数值、日期、boolean
等类型字段。例如:ids
range
term
地理(geo)查询:根据经纬度查询。例如:
geo_distance
geo_bounding_box
复合(compound)查询:复合查询可以将上述各种查询条件组合起来,合并查询条件。例如:
bool
function_score
查询所有 match_all
- 查询所有不用写条件
- 查询出的结果不会列出所有数据,默认只显示前10条
全文检索查询 match/multi_match
match和multi_match的区别是什么?
- match:根据
一个字段
查询 - multi_match:根据
多个字段
查询,参与查询字段越多,查询性能越差
精确查询: term/range
精确查询不会对搜索条件分词
精确查询常见的有哪些?
- term查询:根据
词条
精确匹配,一般搜索keyword类型、数值类型、布尔类型、日期类型字段 - range查询:根据
数值范围
查询,可以是数值、日期的范围。可以写gt(大于、gte(大于等于、lt(小于、lte(小于等于
示例:查询品牌是【如家】和价格区间在【2000-3000】内的酒店
地理查询: geo_bounding_box\geo_distance
根据经纬度
查询。常见的使用场景包括:
- 携程:搜索我附近的酒店
- 滴滴:搜索我附近的出租车
- 微信:搜索我附近的人
示例:查询(31.21,121.5)附近2km内的酒店
复合查询 functions
复合(compound)查询:复合查询可以将其它简单查询组合
起来,实现更复杂的搜索逻辑,例如:
fuction score
:算分函数查询
可以控制文档相关性算分,控制文档排名。例如百度竞价
elasticsearch中的相关性打分算法是什么?
- TF-IDF:在elasticsearch5.0之前, 会随着词频增加而越来越大
- BM25:在elasticsearch5.0之后, 会随着词频增加而增大,但增长曲线会趋于水平
案例:给“如家”这个品牌的酒店排名靠前一些
复合查询–Boolean Query
案例
四、搜索结果处理
排序
elasticsearch支持对搜索结果排序,默认是根据相关度算分(_score
) 来排序。可以排序字段类型有:keyword
类型、数值
类型、地理坐标
类型、日期
类型等。
示例:
分页
elasticsearch默认情况下只返回top10
的数据。而如果要查询更多数据就需要修改分页参数了。
elasticsearch中通过修改from
、size
参数来控制要返回的分页结果:
深度分页问题
常见分页方式
from + size
:
- 优点:支持随机翻页
- 缺点:
深度分页
问题,默认查询上限(from+ size)是10000 场景
:百度、京东、谷歌、淘宝这样的随机翻页搜索
search after
(官方推荐):分页时需要排序,原理时从上一次的排序值开始,查询下一页数据。
- 优点:没有查询上限(单次查询的size不超过10000 )
- 缺点:只能
向后逐页查询
,不支持随机翻页 - 场景:没有随机翻页需求的搜索,例如手机向下滚动翻页
scroll
: 原理将排序数据形成快照,保存在内存
- 优点:没有查询上限(单次查询的size不超过10000)
- 缺点:会有
额外内存消耗
,并且搜索结果是非实时
的 - 场景:海量数据的获取和迁移。从ES7.1开始不推荐,建议用search after方案。
高亮
高亮:就是在搜索结果中把搜索关键字突出显示
。
原理是这样的:
- 将搜索结果中的关键字用标签标记出来
- 在页面中给标签添加css样式
tip
:默认情况下,es搜索字段和高亮字段一致才会高亮。高亮结果标签默认是em
五、RestClient 查询文档
快速入门
match_all查询
查询结果解析
全文检索查询
排序和分页
链式编程
高亮显示
高亮结果解析
高亮结果与查询结果_source
同级,而且高亮结果是个数组(可能不止一处高亮)
实用案例
搜索中给某品牌增加算分