官方文档地址:https://www.elastic.co/guide/en/elasticsearch/reference/index.html
权威指南:https://www.elastic.co/guide/cn/elasticsearch/guide/current/structured-search.html
1. 数据准备
官方测试数据下载地址:https://download.elastic.co/demos/kibana/gettingstarted/accounts.zip ,数据量很大,我们自己构造数据吧。
PUT /user/_doc/1
{
"first_name" : "John",
"last_name" : "Smith",
"age" : 25,
"about" : "I love to go rock climbing",
"interests": [ "sports"]
}
PUT /user/_doc/2
{
"first_name" : "zhangsan",
"last_name" : "Smith",
"age" : 19,
"about" : "我是一个安静的人",
"interests": [ "read" ]
}
PUT /user/_doc/3
{
"first_name" : "lisi",
"last_name" : "Alice",
"age" : 29,
"about" : "我喜欢规划自己的生活",
"interests": [ "sports", "read","music" ]
}
2. match 匹配查询
在匹配之前分析提供的文本,返回与提供的文本、数字、日期或布尔值匹配的文档。 该match
查询是执行全文搜索的标准查询,包括模糊匹配选项。
1. 全文检索
① 底层分词器会对查询文本分词,匹配about字段中含有go或者含有rock的文档:
GET /user/_search
{
"query": {
"match" : {
"about" : {
"query" : "go rock"
}
}
}
}
② 对应的Java调用:
@Slf4j
@Service
public class ElasticSearchImpl {
@Autowired
private RestHighLevelClient restHighLevelClient;
public void searchUser() throws IOException {
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
MatchQueryBuilder matchQueryBuilder = new MatchQueryBuilder("about","go rock");
searchSourceBuilder.query(matchQueryBuilder);
SearchRequest searchRequest = new SearchRequest(new String[]{"user"},searchSourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
System.out.println(searchResponse);
}
}
③ 查询的结果:
{
"took" : 4,
"timed_out" : false,
"_shards" : {
"total" : 7,
"successful" : 7,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 1.464436,
"hits" : [
{
"_index" : "user",
"_type" : "_doc",
"_id" : "1",
"_score" : 1.464436,
"_source" : {
"first_name" : "John",
"last_name" : "Smith",
"age" : 25,
"about" : "I love to go rock climbing",
"interests" : [
"sports"
]
}
}
]
}
}
2. 简化查询DSL语句
GET /user/_search
{
"query": {
"match" : {
"about" : {
"query" : "我是一个"
}
}
}
}
可以简化查询为:
GET /user/_search
{
"query": {
"match" : {
"about" : "我是一个"
}
}
}
{
"took" : 25,
"timed_out" : false,
"_shards" : {
"total" : 7,
"successful" : 7,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 2,
"relation" : "eq"
},
"max_score" : 2.8478274,
"hits" : [
{
"_index" : "user",
"_type" : "_doc",
"_id" : "2",
"_score" : 2.8478274,
"_source" : {
"first_name" : "zhangsan",
"last_name" : "Smith",
"age" : 19,
"about" : "我是一个安静的人",
"interests" : [
"read"
]
}
},
{
"_index" : "user",
"_type" : "_doc",
"_id" : "3",
"_score" : 0.6810339,
"_source" : {
"first_name" : "lisi",
"last_name" : "Alice",
"age" : 29,
"about" : "我喜欢规划自己的生活",
"interests" : [
"sports",
"read",
"music"
]
}
}
]
}
}
3. match 匹配查询原理
查询match
的类型为boolean
。这意味着对提供的文本进行了分析,分析过程根据提供的文本构造了一个布尔查询。该operator
参数可以设置为or
或and
来控制布尔子句(默认为or
),如果为and代表所有字段都要匹配,如果为or代表匹配分词后的任何一个词。
① 带有operator参数and搜索条件,匹配的文档需要包含文本的所有分词,少一个都不行:
GET /user/_search
{
"query": {
"match" : {
"about" : {
"query" : "是一安静个我",
"operator" : "and"
}
}
}
}
@Slf4j
@Service
public class ElasticSearchImpl {
@Autowired
private RestHighLevelClient restHighLevelClient;
public void searchUser() throws IOException {
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
MatchQueryBuilder matchQueryBuilder = new MatchQueryBuilder("about","是一安静个我");
// 设置Operator参数
matchQueryBuilder.operator(Operator.AND);
searchSourceBuilder.query(matchQueryBuilder);
SearchRequest searchRequest = new SearchRequest(new String[]{"user"},searchSourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
System.out.println(searchResponse);
}
}
{
"took" : 2,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 2.8478274,
"hits" : [
{
"_index" : "user",
"_type" : "_doc",
"_id" : "2",
"_score" : 2.8478274,
"_source" : {
"first_name" : "zhangsan",
"last_name" : "Smith",
"age" : 19,
"about" : "我是一个安静的人",
"interests" : [
"read"
]
}
}
]
}
}
② 带有operator参数or搜索条件,匹配的文档需要包含文本的任意一个分词:
GET /user/_search
{
"query": {
"match" : {
"about" : "是一个我"
}
}
}
@Slf4j
@Service
public class ElasticSearchImpl {
@Autowired
private RestHighLevelClient restHighLevelClient;
public void searchUser() throws IOException {
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
MatchQueryBuilder matchQueryBuilder = new MatchQueryBuilder("about","是一个我");
// 设置Operator参数
matchQueryBuilder.operator(Operator.OR);
searchSourceBuilder.query(matchQueryBuilder);
SearchRequest searchRequest = new SearchRequest(new String[]{"user"},searchSourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
System.out.println(searchResponse);
}
}
{
"took" : 29,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 2,
"relation" : "eq"
},
"max_score" : 2.8478274,
"hits" : [
{
"_index" : "user",
"_type" : "_doc",
"_id" : "2",
"_score" : 2.8478274,
"_source" : {
"first_name" : "zhangsan",
"last_name" : "Smith",
"age" : 19,
"about" : "我是一个安静的人",
"interests" : [
"read"
]
}
},
{
"_index" : "user",
"_type" : "_doc",
"_id" : "3",
"_score" : 0.6810339,
"_source" : {
"first_name" : "lisi",
"last_name" : "Alice",
"age" : 29,
"about" : "我喜欢规划自己的生活",
"interests" : [
"sports",
"read",
"music"
]
}
}
]
}
}