TypechoJoeTheme

IT技术分享

统计

05. ES全文检索查询——ElasticSearch搜索专栏

2022-06-14
/
0 评论
/
915 阅读
/
正在检测是否收录...
06/14

不同于结构化查询,全文搜索首先对查询词进行分析,然后根据查询词的分词结果构建查询。

这里所说的全文指的是文本类型数据(text类型),默认的数据形式是人类的自然语言

结构化搜索关注的是数据是否匹配,全文搜索关注的是匹配的程度;

结构化搜索一般用于精确匹配,而全文搜索用于部分匹配。

一、Match查询

match查询是全文搜索的主要代表。

对于最基本的math搜索来说,只要分词中的一个或者多个在文档中存在即可。

例如搜索“金都酒店”,查询词先被分词器切分为“金都”、“酒店”

因此,只要文档中包含这2个词中的任何一个,都会被搜索到。

1.1 DSL方式

GET /hotel/_search
{
  "_source": ["title"],      //只返回title字段
  "query": {
   "match": {                //匹配title字段为“金都酒店”的文档
      "title": "金都酒店"
    }
  }
}

match搜索可以设置operator参数,该参数决定文档按照分词后的词集合进行“与”还是“或”匹配。

在默认情况下,该参数的值为“或”关系,即operator的值为or

下面的请求示例设置查询词之间的匹配结果为“与”关系:

GET /hotel/_search
{
  "_source": ["title"],
  "query": {
    "match": {
      "title":{
        "query": "金都",
        "operator":"and"      //查询词之间的匹配结果为“与”关系
      }
    }
  }
}

这时可以采用minimum_should_match参数,该参数叫作最小匹配参数,

其值为一个数值,意义为可以匹配上的词的个数。

实际应用中更常用的做法是将其设置为一个百分数,因为我们无法控制用户查询时输入的单词数量

GET /hotel/_search
{
  "_source": ["title"],
  "query": {
    "match": {
      "title": {                          //match搜索条件
        "query": "金都",
        "operator": "or",
        "minimum_should_match": "80%"     //设置最小匹配度为80%
      }
    }
  }
}

以上语句执行match查询的步骤如下:

(1)检查字段类型。title字段是text类型(内容会被分词),说明此字段在存储时和查询时都会进行分词,而且在存储时会建立倒排索引。

(2)分析查询字符串。将查询的字符串"金都"传入分词器中,输出的结果是单词"金都"。因为只有一个单词,所以match查询执行的是单个底层term查询。

(3)查找匹配的文档。用term查询在倒排索引中查找"金都",然后获取一组包含该单词的文档数据。

(4)为每个文档评分。用term查询计算出每个文档的评分。

  • match查询最终其实会转化为term查询
  • 使用match查询时,返回结果中文档的评分是和该文档中字段的内容长度有关的,即字段内容越短,评分就越高

1.2 Java 客户端方式

在Java客户端上可以使用QueryBuilders.matchQuery()方法构建match请求,

分别给该方法传入字段名称和查询值即可进行match查询。

public void matchSearch() {
    SearchRequest searchRequest = new SearchRequest();  //新建搜索请求
    SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
    searchSourceBuilder.query(QueryBuilders.matchQuery("title", "金都")
        .operator(Operator.AND));   //新建match查询,并设置operator值为and
    searchRequest.source(searchSourceBuilder);         //设置查询
   printResult(searchRequest);                         //打印结果
}

二、multi_match查询

有时用户需要在多个字段中查询关键词,除了使用布尔查询封装多个match查询之外,可替代的方案是使用multi_match。

可以在multi_match的query子句中组织数据匹配规则,并在fields子句中指定需要搜索的字段列表。

2.1 DSL方式

GET /hotel/_search
{
  "_source": ["title","amenities"],
  "query": {
    "multi_match": {
      "query": "假日",            //匹配关键字为“假日”
      "fields": [                 //设置匹配的字段为title和amenities
        "title",
        "amenities"
      ]
    }
  }
}
他们之间是或的关系

2.2 Java 客户端方式

public void multiMatchSearch() {
    SearchRequest searchRequest = new SearchRequest();  //新建搜索请求
    SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
    //新建multi_match查询,从"title"和"amenities"字段查询"假日"
    searchSourceBuilder.query(QueryBuilders.multiMatchQuery("假日", "title", "amenities"));
    searchRequest.source(searchSourceBuilder);    //设置查询
   printResult(searchRequest);                    //打印结果
}

三、match_phrase查询

match_phrase用于匹配短语,与match查询不同的是,match_phrase用于搜索确切的短语或邻近的词语。

假设在酒店标题中搜索“文雅酒店”,

希望酒店标题中的“文雅”与“酒店”紧邻并且“文雅”在“酒店”前面,则使用match_phrase查询

3.1 DSL方式

GET /hotel/_search
{
  "query": {
    "match_phrase": {
      "title": "文雅酒店"
    }
  }
}

可以设置match_phrase查询的slop参数,它用来调节匹配词之间的距离阈值。

默认slop = 0, 也就是必需紧挨着

GET /hotel/_search
{
  "query": {
    "match_phrase": {
      "title": {
        "query": "文雅酒店",
        "slop": 2              //将“文雅”和“酒店”之间的最大匹配距离设置为2
      }
    }
  }
}

3.2 Java 客户端方式

在Java客户端上可以使用QueryBuilders.matchPhraseQuery()方法构建match_phrase请求,

分别给该方法传入查询字段和值即可进行match_phrase查询。

public void matchPhraseSearch() {
    SearchRequest searchRequest = new SearchRequest(); //新建搜索请求
    SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
    //新建match_phrase查询,并设置slop值为2
    QueryBuilder matchPhraseQueryBuilder=QueryBuilders.matchPhraseQuery("title","文雅酒店").slop(2);
    searchSourceBuilder.query(matchPhraseQueryBuilder);
    searchRequest.source(searchSourceBuilder);  //设置查询
   printResult(searchRequest);                  //打印结果
}

四、query_string查询

4.1 DSL方式

GET /dbindex/_search
{
  "query": {
    "query_string": {
      "query": "(dog and) AND (beautiful)",
      "default_field": "title"
    }
  }
}

五、simple_query_string查询

simple_query_string查询是一种使用简单的语法来解析要查询的字符串,并将其拆分为基于特殊运算符的查询方式。

其语法比query_string查询更受限制,但simple_query_string查询在遭遇无效语法事不会返回错误提示信息

5.1 DSL方式

GET /dbindex/_search
{
  "query": {
    "simple_query_string" : {
        "query": "\"the dog\" + (flower | and) + beautiful",
        "fields": ["title"],
        "default_operator": "and"
    }
  }
}
在以上语句中,查询索引库的title字段,必须匹配到beautiful单词,并且必须匹配dog和and其中任何一个单词的字段

六、intervals查询

intervals是时间间隔的意思,在Elasticsearch中它本质上是将多个规则按照顺序匹配。

6.1 DSL方式

GET /dbindex/_search
{
  "query": {
    "intervals" : {
      "title" : {
        "all_of" : {
          "ordered" : true,
          "intervals" : [
            {
              "match" : {
                "query" : "flower", // 文档内容先匹配"flower"单词
                "max_gaps" : 0,
                "ordered" : true
              }
            },
            {
              "any_of" : {
                "intervals" : [   // 文档内容再匹配"beautiful"和"dog"两个单词中的其中一个
                  { "match" : { "query" : "beautiful" } },
                  { "match" : { "query" : "dog" } }
                ]
              }
            }
          ]
        }
      }
    }
  }
}

七、高亮查询

7.1 DSL方式

GET /dbindex/_doc/_search
{

  "query":{
  "match": {
    "name": "贾诩"
  }
  },
  "highlight":{
    "fields": {
      "name": {}
    }
  }
}

返回结果

{
  "took" : 6,
  …
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 1.5098253,
    "hits" : [
      {
        "_index" : "myindex_highlight",
        "_type" : "_doc",
        "_id" : "UhAeYXoBiBO67Reoue-V",
        "_score" : 1.5098253,
        "_source" : {
          "name" : "贾诩",
          "address" : "魏国",
          "age" : 19
        },
        "highlight" : {  //高亮标签
          "name" : [
            "<em>贾</em><em>诩</em>"
          ]
        }
      }
    ]
  }
}

八、自定义高亮查询

8.1 DSL方式

GET dbindex/_doc/_search
{
  "query":{
  "match": {
    "name": "贾诩"
  }
  },
  "highlight":{
    "pre_tags": "<p class='gaoliang'>", //自定义高亮显示效果的标签
    "post_tags": "</p>",
    "fields": {
      "name": {}
    }
  }
}
朗读
赞 · 0
版权属于:

IT技术分享

本文链接:

https://idunso.com/archives/2872/(转载时请注明本文出处及文章链接)