05-ElasticSearch高级搜索

打印 上一主题 下一主题

主题 926|帖子 926|积分 2778

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查询语法如下所示

      1. GET /indexName/_search
      2. {
      3.   "query": {
      4.     "match":{
      5.       "FIELD": "TEXT"
      6.     }
      7.   }
      8. }
      复制代码

  • match_all查询语法如下

      1. GET /indexName/_search
      2. {
      3.   "query": {
      4.     "multi_match": {
      5.       "query": "TEXT",
      6.       "fileds": ["FILED1", "FILED2"]
      7.     }
      8.   }
      9. }
      复制代码

2.1.3、match查询DSL语句示例&&RestAPI示例

①、DSL语句


  • 比如要搜索name字段中存在 如家酒店,DSL语句如下所示

      1. GET hotel/_search
      2. {
      3.   "query": {
      4.     "match": {
      5.       "name": "如家酒店"
      6.     }
      7.   },
      8.   "size": 2                # size的意思是只显示n条数据
      9. }
      复制代码

  • 搜索结果如下所示



  • 结果分析

    • 因为name字段是类型是text,搜索的时候会对这个字段进行分词
    • 如搜索如家酒店,那么就会分词称为如家,酒店,相当于会搜索三次,并取这三次搜索的并集(ES默认的是并集),所以搜索的命中率才会如此之高

      • 通俗的来说

        • 并集就相当于搜索到name like %如家%算一条数据,搜索到酒店也算一条数据
        • 那么交集就跟它相反,必须是name like %如家酒店%才能算是一条数据


    • 那么如何取交集呢?,如下所示

      • DSL

          1. # 取交集,并集是or
          2. GET hotel/_search
          3. {
          4.   "query": {
          5.     "match": {
          6.       "name": {
          7.         "query": "如家酒店",
          8.         "operator": "and"
          9.       }
          10.     }
          11.   }
          12. }
          复制代码

      • 运行结果





②、RestAPI

math_all


  • 代码如下所示

      1. package com.coolman.hotel.test;
      2. import com.coolman.hotel.pojo.HotelDoc;
      3. import com.fasterxml.jackson.core.JsonProcessingException;
      4. import com.fasterxml.jackson.databind.ObjectMapper;
      5. import org.apache.lucene.search.TotalHits;
      6. import org.elasticsearch.action.search.SearchRequest;
      7. import org.elasticsearch.action.search.SearchResponse;
      8. import org.elasticsearch.client.RequestOptions;
      9. import org.elasticsearch.client.RestHighLevelClient;
      10. import org.elasticsearch.index.query.MatchAllQueryBuilder;
      11. import org.elasticsearch.index.query.QueryBuilder;
      12. import org.elasticsearch.index.query.QueryBuilders;
      13. import org.elasticsearch.search.SearchHit;
      14. import org.elasticsearch.search.SearchHits;
      15. import org.junit.jupiter.api.Test;
      16. import org.springframework.beans.factory.annotation.Autowired;
      17. import org.springframework.boot.test.context.SpringBootTest;
      18. import java.io.IOException;
      19. @SpringBootTest
      20. public class FullTextSearchDemo {
      21.     // 注入 RestHighLevelClient对象
      22.     @Autowired
      23.     private RestHighLevelClient restHighLevelClient;
      复制代码
      1. // jackson
      2. private final ObjectMapper objectMapper = new ObjectMapper();
      3. /**
      4. * 查询所有测试
      5. */
      6. @Test
      7. public void testMatchAll() throws IOException {
      8.     // 1. 创建一个查询请求对象
      9.     SearchRequest searchRequest = new SearchRequest("hotel");   // 指定索引
      10.     // 2. 添加查询的类型
      11.     MatchAllQueryBuilder matchAllQueryBuilder = QueryBuilders.matchAllQuery();
      12.     searchRequest.source().query(matchAllQueryBuilder);     // source就相当于{}
      13.     searchRequest.source().size(100);     // RestAPI默认返回的是10条数据,可以更改size的属性,即可自定义返回的数据量
      14.     // 3. 发出查询的请求,得到响应结果
      15.     SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
      16.     // 4. 处理响应的结果
      17.     handlerResponse(response);
      18. }
      19. /**
      20. * 用来处理响应数据(相当于解析返回的JSON数据)
      21. * @param response
      22. */
      23. private void handlerResponse(SearchResponse response) throws JsonProcessingException {
      24.     // 1. 得到命中的数量(即总记录数量)
      25.     SearchHits hits = response.getHits();
      26.     long totalCount = hits.getTotalHits().value;// 总记录数
      27.     System.out.println("总记录数量为:" + totalCount);
      28.     // 2. 获取本次查询出来的列表数据
      29.     SearchHit[] hitsArray = hits.getHits();
      30.     for (SearchHit hit : hitsArray) {
      31.         // 得到json字符串
      32.         String json = hit.getSourceAsString();
      33.         // 将json字符串转换为实体类对象
      34.         HotelDoc hotelDoc = objectMapper.readValue(json, HotelDoc.class);
      35.         System.out.println(hotelDoc);
      36.     }
      37. }
      复制代码
      }
      ​~~~

match


  • 代码如下所示

      1.     /**
      2.      * 单字段查询
      3.      */
      4.     @Test
      5.     public void testMatch() throws IOException {
      6.         // 1. 创建查询请求对象
      7.         SearchRequest searchRequest = new SearchRequest("hotel");
      8.         // 2. 添加查询的类型
      9.         MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("name", "如家酒店");
      10.         searchRequest.source().query(matchQueryBuilder);
      11.         // 3. 发出查询请求,得到响应数据
      12.         SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
      13.         // 4. 处理响应的结果
      14.         handlerResponse(response);
      15.     }
      复制代码

自行运行查看结果即可
2.1.4、multi_match查询DSL语句示例&&RestAPI示例

DSL语句


  • 比如搜索name和brand字段中出现如家酒店的数据

    • DSL语句如下所示

        1. GET hotel/_search
        2. {
        3.   "query": {
        4.     "multi_match": {
        5.       "query": "如家酒店",
        6.       "fields": ["name", "brand"]
        7.     }
        8.   }
        9. }
        复制代码

    • 运行结果如下所示



    • 不过多字段查询的使用很少,因为多字段查询会使得查询效率变慢
    • 一般都会在创建映射的时候,使用copy_to将指定字段的值拷贝到另一个字段,如自定义的all字段
    • 这样子就可以使用单字段查询,提高查询效率

RestAPI

跟单字段查询差不多,只不过使用QueryBuilders创建的对象略有不同罢了


  • 代码如下所示

      1.     /**
      2.      * 多字段查询
      3.      */
      4.     @Test
      5.     public void testMultiMatch() throws IOException {
      6.         // 1. 创建查询请求球体对象
      7.         SearchRequest searchRequest = new SearchRequest("hotel");
      8.         // 2. 添加要查询的字段
      9. //        MultiMatchQueryBuilder multiMatchQueryBuilder = QueryBuilders.multiMatchQuery("如家酒店", "name", "brand", "bussiness");
      10. //        searchRequest.source().query(multiMatchQueryBuilder);
      11.         // 因为在创建映射的时候使用了copy_to,索引上面的多字段查询等价于下面的单字段查询
      12.         MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("all", "如家酒店");
      13.         searchRequest.source().query(matchQueryBuilder);
      14.         // 3. 执行查询操作,得到响应对象
      15.         SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
      16.         // 4. 处理响应对象
      17.         handlerResponse(response);
      18.     }
      复制代码

2.2、精准查询

2.2.1、使用场景

<ul>精确查询一般是查找keyword、数值、日期、boolean等类型的字段,所以不会对搜索条件分词,常见的有如下<ul>
term

  • 根据词条精确值查询,相当于equals、=
range<ul>
根据值的范围查询,相当于>=、

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

数据人与超自然意识

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表