ToB企服应用市场:ToB评测及商务社交产业平台
标题:
05-ElasticSearch高级搜索
[打印本页]
作者:
数据人与超自然意识
时间:
2022-9-16 17:15
标题:
05-ElasticSearch高级搜索
2、ElasticSearch高级搜索
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
2.1、全文检索查询
2.1.1、使用场景
全文检索查询的基本流程如下所示
①、对用户搜索的内容做分词,得到词条
②、根据词条去倒排索引库中匹配,得到文档id
③、根据文档id找到文档,把所有匹配结果以并集或交集返回给用户
比较常用的场景包括
商城的输入框搜索
百度搜索框搜索
因为是拿着词条去匹配,因此参与搜索的字段也必须是可分词的text类型的字段
2.1.2、DSL语句格式
常见的全文检索查询包括
match查询:单字段查询
multi_match查询:多字段查询,任意一个字段符合条件就算符合查询条件
match查询语法如下所示
GET /indexName/_search
{
"query": {
"match":{
"FIELD": "TEXT"
}
}
}
复制代码
match_all查询语法如下
GET /indexName/_search
{
"query": {
"multi_match": {
"query": "TEXT",
"fileds": ["FILED1", "FILED2"]
}
}
}
复制代码
2.1.3、match查询DSL语句示例&&RestAPI示例
①、DSL语句
比如要搜索name字段中存在 如家酒店,DSL语句如下所示
GET hotel/_search
{
"query": {
"match": {
"name": "如家酒店"
}
},
"size": 2 # size的意思是只显示n条数据
}
复制代码
搜索结果如下所示
结果分析
因为name字段是类型是text,搜索的时候会对这个字段进行分词
如搜索如家酒店,那么就会分词称为如家,酒店,
相当于会搜索三次,并取这三次搜索的并集(ES默认的是并集),
所以搜索的命中率才会如此之高
通俗的来说
并集就相当于搜索到name like %如家%算一条数据,搜索到酒店也算一条数据
那么交集就跟它相反,必须是name like %如家酒店%才能算是一条数据
那么如何取交集呢?,如下所示
DSL
# 取交集,并集是or
GET hotel/_search
{
"query": {
"match": {
"name": {
"query": "如家酒店",
"operator": "and"
}
}
}
}
复制代码
运行结果
②、RestAPI
math_all
代码如下所示
package com.coolman.hotel.test;
import com.coolman.hotel.pojo.HotelDoc;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.lucene.search.TotalHits;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.MatchAllQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.io.IOException;
@SpringBootTest
public class FullTextSearchDemo {
// 注入 RestHighLevelClient对象
@Autowired
private RestHighLevelClient restHighLevelClient;
复制代码
// jackson
private final ObjectMapper objectMapper = new ObjectMapper();
/**
* 查询所有测试
*/
@Test
public void testMatchAll() throws IOException {
// 1. 创建一个查询请求对象
SearchRequest searchRequest = new SearchRequest("hotel"); // 指定索引
// 2. 添加查询的类型
MatchAllQueryBuilder matchAllQueryBuilder = QueryBuilders.matchAllQuery();
searchRequest.source().query(matchAllQueryBuilder); // source就相当于{}
searchRequest.source().size(100); // RestAPI默认返回的是10条数据,可以更改size的属性,即可自定义返回的数据量
// 3. 发出查询的请求,得到响应结果
SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
// 4. 处理响应的结果
handlerResponse(response);
}
/**
* 用来处理响应数据(相当于解析返回的JSON数据)
* @param response
*/
private void handlerResponse(SearchResponse response) throws JsonProcessingException {
// 1. 得到命中的数量(即总记录数量)
SearchHits hits = response.getHits();
long totalCount = hits.getTotalHits().value;// 总记录数
System.out.println("总记录数量为:" + totalCount);
// 2. 获取本次查询出来的列表数据
SearchHit[] hitsArray = hits.getHits();
for (SearchHit hit : hitsArray) {
// 得到json字符串
String json = hit.getSourceAsString();
// 将json字符串转换为实体类对象
HotelDoc hotelDoc = objectMapper.readValue(json, HotelDoc.class);
System.out.println(hotelDoc);
}
}
复制代码
}
~~~
match
代码如下所示
/**
* 单字段查询
*/
@Test
public void testMatch() throws IOException {
// 1. 创建查询请求对象
SearchRequest searchRequest = new SearchRequest("hotel");
// 2. 添加查询的类型
MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("name", "如家酒店");
searchRequest.source().query(matchQueryBuilder);
// 3. 发出查询请求,得到响应数据
SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
// 4. 处理响应的结果
handlerResponse(response);
}
复制代码
自行运行查看结果即可
2.1.4、multi_match查询DSL语句示例&&RestAPI示例
DSL语句
比如搜索name和brand字段中出现如家酒店的数据
DSL语句如下所示
GET hotel/_search
{
"query": {
"multi_match": {
"query": "如家酒店",
"fields": ["name", "brand"]
}
}
}
复制代码
运行结果如下所示
不过多字段查询的使用很少,因为多字段查询会使得查询效率变慢
一般都会在创建映射的时候,使用copy_to
将指定字段的值拷贝到另一个字段
,如自定义的all字段
这样子就可以使用单字段查询,提高查询效率
RestAPI
跟单字段查询差不多,只不过使用QueryBuilders创建的对象略有不同罢了
代码如下所示
/**
* 多字段查询
*/
@Test
public void testMultiMatch() throws IOException {
// 1. 创建查询请求球体对象
SearchRequest searchRequest = new SearchRequest("hotel");
// 2. 添加要查询的字段
// MultiMatchQueryBuilder multiMatchQueryBuilder = QueryBuilders.multiMatchQuery("如家酒店", "name", "brand", "bussiness");
// searchRequest.source().query(multiMatchQueryBuilder);
// 因为在创建映射的时候使用了copy_to,索引上面的多字段查询等价于下面的单字段查询
MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("all", "如家酒店");
searchRequest.source().query(matchQueryBuilder);
// 3. 执行查询操作,得到响应对象
SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
// 4. 处理响应对象
handlerResponse(response);
}
复制代码
2.2、精准查询
2.2.1、使用场景
<ul>精确查询一般是查找keyword、数值、日期、boolean等类型的字段,所以
不会对搜索条件分词
,常见的有如下<ul>
term
根据词条精确值查询,相当于equals、=
range<ul>
根据值的范围查询,相当于>=、
欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/)
Powered by Discuz! X3.4