09、ES实战:全文查询

本学习笔记基于ElasticSearch 7.10版本,旧版本已经废弃的查询功能暂时不做笔记,以后有涉及到再做补充。
参考官方文档:https://www.elastic.co/guide/en/elasticsearch/reference/7.10/full-text-queries.html

一、match

match 会对查询语句进行分词,分词后,如果查询语句中的任何一个词项被匹配,则文档就会被索引到。

# 先查询两个不相关的关键字
GET books/_search
{
   
     
  "query": {
   
     
    "match": {
   
     
      "name": "美术"
    }
  }
}
GET books/_search
{
   
     
  "query": {
   
     
    "match": {
   
     
      "name": "计算机"
    }
  }
}
# 再合并查询两个关键字
GET books/_search
{
   
     
  "query": {
   
     
    "match": {
   
     
      "name": "美术计算机"
    }
  }
}

单独查询美术计算机时,查询到符合条件的文档数分别是 9 和 46 条。
合并查询时会对美术计算机进行分词,分词之后再去查询,只要文档中包含任意一个分词,就回返回文档,最后查询到符合条件的文档树正好是55条。

可以看到,分词后词项之间是 OR 的关系,如果想要修改,也可以通过 operator 改为 AND:

GET books/_search
{
   
     
  "query": {
   
     
    "match": {
   
     
      "name": {
   
     
        "query": "十一五计算机",
        "operator": "and"
      }
    }
  }
}

二、match_phrase

match_phrase 就是短语查询,也会对查询的关键字进行分词,但是它分词后有两个特点:

  • 分词后的词项顺序必须和文档中词项的顺序一致
  • 所有的词都必须出现在文档中

但是注意,这里直接使用前面十一五计算机短语,并不能查询到文档,因为分词之后,关键字之间还间隔这国家级规划教材:大学这些内容。
*
这种情况可以使用 slop 参数来指定关键字之间的距离,注意这个距离,不是指关键字之间间隔的字数,而是指它们之间的 position 位置的间隔。

什么是position
每份文档中的字段被分词器解析之后,解析出来的词项都包含一个 position 字段表示词项的位置。每份文档的 position 都从 0 开始,每个词项递增 1 。

使用ik分词器测试如下:

GET books/_analyze
{
   
     
  "text": "普通高等教育“十一五”国家级规划教材:大学计算机基础",
  "analyzer": "ik_max_word"
}
# 分词结果
{
   
     
  "tokens" : [
    ...
    {
   
     
      "token" : "十一五",
      "start_offset" : 7,
      "end_offset" : 10,
      "type" : "CN_WORD",
      "position" : 4
    },
    {
   
     
      "token" : "十一",
      "start_offset" : 7,
      "end_offset" : 9,
      "type" : "CN_WORD",
      "position" : 5
    },
    {
   
     
      "token" : "五",
      "start_offset" : 9,
      "end_offset" : 10,
      "type" : "CN_CHAR",
      "position" : 6
    },
    {
   
     
      "token" : "国家级",
      "start_offset" : 11,
      "end_offset" : 14,
      "type" : "CN_WORD",
      "position" : 7
    },
    {
   
     
      "token" : "国家",
      "start_offset" : 11,
      "end_offset" : 13,
      "type" : "CN_WORD",
      "position" : 8
    },
    {
   
     
      "token" : "级",
      "start_offset" : 13,
      "end_offset" : 14,
      "type" : "CN_CHAR",
      "position" : 9
    },
    {
   
     
      "token" : "规划",
      "start_offset" : 14,
      "end_offset" : 16,
      "type" : "CN_WORD",
      "position" : 10
    },
    {
   
     
      "token" : "教材",
      "start_offset" : 16,
      "end_offset" : 18,
      "type" : "CN_WORD",
      "position" : 11
    },
    {
   
     
      "token" : "大学",
      "start_offset" : 19,
      "end_offset" : 21,
      "type" : "CN_WORD",
      "position" : 12
    },
    {
   
     
      "token" : "计算机",
      "start_offset" : 21,
      "end_offset" : 24,
      "type" : "CN_WORD",
      "position" : 13
    },
    ...
  ]
}

分词后十一五 最后出现的 position = 6 ,而 计算机 第一次出现的 position = 13,中间间隔了 6 个位置。所以只需要设置 slop 为 6 即可查询到文档:

GET books/_search
{
   
     
  "query": {
   
     
    "match_phrase": {
   
     
      "name": {
   
     
        "query": "十一五计算机",
        "slop": 6
      }
    }
  }
}

三、match_phrase_prefix

类似于match_phrase 查询,只不过这里多了一个通配符,match_phrase_prefix 将最后一个词项作为前缀去查询匹配,但是由于这种匹配方式效率较低,因此大家作为了解即可。

GET books/_search
{
   
     
  "query": {
   
     
    "match_phrase_prefix": {
   
     
      "name": {
   
     
        "query": "计",
        "max_expansions": 1
      }
    }
  }
}

这个查询过程,会自动进行词项匹配,会自动查找以 开始的词项,默认是 10 个,我们可以通过 max_expansions 控制值匹配的词项个数。例如以 开始的词项控制匹配个数为 1 、2 、3 时,匹配到的词项分别为 计分、计划、计算

注意match_phrase_prefix 是针对分片级别的查询,每个分片匹配的词项可能不一致。我们现在练习创建的索引分片数为 1 ,所以使用起来并不会有什么问题。但是如果分片数大于 1 时,查询结果就可能有问题。

match_phrase_prefix 为 1 ,分片数为 3 举例,可能会查询出 3 个匹配词项对应的文档:

分片数 匹配词项 文档数
分片1 计分 2
分片2 计划 1
分片3 计算 46

四、multi_match

match 查询的升级版,可以指定多个查询域:

GET books/_search
{
   
     
  "query": {
   
     
    "multi_match": {
   
     
      "query": "java",
      "fields": ["name","info"]
    }
  }
}

这种查询方式还可以指定字段的权重:

GET books/_search
{
   
     
  "query": {
   
     
    "multi_match": {
   
     
      "query": "java",
      "fields": ["name^4","info"]
    }
  }
}

这个表示关键字出现在 name 中的权重是出现在 info 中权重的 4 倍。

五、query_string

query_string 是一种紧密结合 Lucene 的查询方式,在一个查询语句中可以用到 Lucene 的一些查询语法:

GET books/_search
{
   
     
  "query": {
   
     
    "query_string": {
   
     
      "default_field": "name",
      "query": "(十一五) AND (计算机)"
    }
  }
}

六、simple_query_string

这个是query_string 的升级,可以直接使用 +、|、- 代替 AND、OR、NOT 等。

注意: simple_query_string 使用 fields 来指定查询的字段,即使只指定一个字段,值也必须为数组类型:

GET books/_search
{
   
     
  "query": {
   
     
    "simple_query_string": {
   
     
      "fields": ["name"],
      "query": "(十一五) + (计算机)"
    }
  }
}

版权声明:

本文仅记录ElasticSearch学习心得,如有侵权请联系删除。
更多内容请访问原创作者:江南一点雨
*

版权声明:本文不是「本站」原创文章,版权归原作者所有 | 原文地址: