ElasticSearch系列 - SpringBoot整合ES之全文搜索匹配查询 match


官方文档地址: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参数可以设置为orand 来控制布尔子句(默认为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"
          ]
        }
      }
    ]
  }
}
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我一直在流浪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值