Elasticsearch查询过滤解惑

Elasticsearch查询过滤解惑简介 之前一直被查询(query)与过滤(filter)所困惑,为什么同样是bool在一个地方就是查询,在另一个地方就是过滤了。 后来仔细的看了一下官方文档才发现,都是查询,只是区分: query …

Elasticsearch查询过滤解惑

简介

之前一直被查询(query)与过滤(filter)所困惑,为什么同样是bool在一个地方就是查询,在另一个地方就是过滤了。

后来仔细的看了一下官方文档才发现,都是查询,只是区分:

  1. query context(查询上下文)
  2. filter context(过滤上下文)

为什么要区分query context与filter context呢?

因为效率不同,在 filter context中的查询更加高效,因为filter context不会计算相关性评分,并且ES会自动缓存高频过滤查询。

哪些是过滤上下文

首先看到filter肯定是了,另外在bool查询中的must_not也会在filter context中执行。

filter

bool查询:

{
  "query": { 
    "bool": { 
      "filter": [ 
        { "term":  { "status": "1" }},
        { "range": { "create_date": { "lte": "2020-01-01" }}}
      ]
    }
  }
}

constant_score查询:

{
    "query": {
        "constant_score" : {
            "filter" : {
                "term" : { "user" : "tim"}
            },
            "boost" : 1.2
        }
    }
}

聚合函数中:

{
  "aggs" : {
      "month" : {
          "filter" : { "term": { "type": "2" } }
      }
  }
}

must_not

{
  "query": {
    "bool" : {
      "must_not" : {
        "range" : {
          "age" : { "gte" : 18, "lte" : 30 }
        }
      }
    }
  }
}

bool查询

类型 说明
must 表示条件必须满足,多个条件之间的关系是and,表示同时满足
should 表示至少匹配一个,多个条件之间的关系是or,表示至少满足一个
filter 条件必须满足,和must不同,filter在过滤上下文执行,不计算相关性得分
must_not 条件必须不满足,在过滤上下文执行,不计算相关性得分

注意:must_not是在filter context(过滤上下文执行)

{
  "query": {
    "bool" : {
      "must" : {
        "term" : { "status" : 1 }
      },
      "filter": {
        "term" : { "type" : "Component" }
      },
      "must_not" : {
        "range" : {
          "ctime" : { "gte" : "2019-12-01", "lte" : "2020-01-01" }
        }
      },
      "should" : [
        { "term" : { "tag" : "Kafka" } },
        { "term" : { "tag" : "Elasticsearch" } }
      ]
    }
  }
}

如上所示,term表示term查询,表示精确匹配,range查询是范围匹配。

上面的查询的含义是,文档中status字段必须为1,type字段必须是”Component”,ctime字段必须在2019-12-01到2020-01-01这个范围之内,tag字段必须包含”Kafka”或者”Elasticsearch”。

全文搜索查询

match

match最常用,做的就是对应字段的全文索引。

{
  "match" : {
        "lauguage" : "Java"
    }
}
{
    "query": {
        "match" : {
            "message" : {
                "query" : "java python ruby"
            }
        }
    }
}

multi_match

multi_match和match差不多,但是可以指定多个字段搜索。

{
  "query": {
    "multi_match" : {
      "query":    "java python ruby", 
      "fields": [ "subject", "message" ] 
    }
  }
}

match_all

match_all可以查询到所有索引字段,没有查询条件下的默认使用match_all。

{
  "match_all" : {}
}

match_phrase

match_phrase和match有点相似,但是有2点很大区别:

  1. 查询分词的单词必须要在文档相应字段分词中全部出现
  2. 单词出现的顺序也必须一致
{
    "query": {
        "match_phrase" : {
            "message" : "java python ruby"
        }
    }
}

出现相对位置可以使用slop参数调整

{
  "query": {
      "match_phrase": {
          "message": {
              "query": "java python ruby",
              "slop": 2
          }
      }
  }
}

可以参考下面的查询示例,下面是测试数据: slop-all

no-slop

如上图所示,是没有slop参数的查询结果。

slop2

如上图所示,是slop参数为2的查询结果。

slop3

如上图所示,是slop参数为3的查询结果。

我们可以看到,slop参数就是调整查询单词中能间隔slop-1个单词。

match_phrase_prefix

match_phrase_prefix和match_phrase差不多,但是运行前缀匹配

{
    "query": {
        "match_phrase_prefix" : {
            "message" : {
                "query" : "java python r"
            }
        }
    }
}

其他常用查询

出来我们上面介绍的bool查询、全文搜索查询以及涉及到的term、range等查询,我们还有一些其他常用的查询,下面我们就简单的介绍一下。

terms

前面我们已经有提到term查询,表示精确匹配,terms和term基本一样,但是terms允许设置多个值,只要有一个值精确匹配就算匹配成功。

{
  "query" : {
      "terms" : {
          "component" : ["kafka", "elasticsearch"],
          "boost" : 1.5
      }
  }
}

如上所示,表示只要component字段中精确匹配到kafka 或者 elasticsearch就算匹配成功。

boost影响文档相关性,大于1表示计算时增加文档相关性,小于1表示计算时减小文档相关性。

terms_set

terms_set查询是给定一个数组,如果文档中的对应字段包含至少指定个值在参数数组中就匹配。

听起来有点绕,没有关系,我们看一个示例,先创建一个user索引,然后添加2个文档如下。

PUT /user/_doc/1?refresh

{
    "name": "tim",
    "hobby": ["看书", "跑步"],
    "required_matches": 2
}

PUT /user/_doc/2?refresh

{
    "name": "allen",
    "hobby": ["看书", "冥想"],
    "required_matches": 2
}

下面我们就可以执行terms_set查询了。 GET /user/_search

{
    "query": {
        "terms_set": {
            "hobby.keyword": {
                "terms": ["看书", "游泳", "冥想"],
                "minimum_should_match_field": "required_matches"
            }
        }
    }
}

如上所示,查询中使用的是hobby.keyword,而不是hobby,是因为添加user映射的时候没有设置mapping,自动映射hobby为text类型,但是自动映射还使用了fields参数,所以我们可以使用hobby.keyword来搜索。

如果怕麻烦,可以直接设置一下mapping,把hobby设置为keyword类型。

上面的搜索会查询到name为allen的文档,如果我们把”冥想”换成”跑步”就会搜索到name为tim的文档。

感觉比较蛋疼的是最小匹配个数要在文档中设置,而不是直接在查询中设置值,在查询中使用的是引用文档中最小匹配的字段

exists

{
    "query": {
        "exists": {
            "field": "gid"
        }
    }
}

ids

{
    "query": {
        "ids" : {
            "values" : ["1", "3", "5", "7", "9"]
        }
    }
}

prefix

前缀匹配有时候非常有用,比如说我们要找老王:

{
  "query": {
      "prefix" : { "name" : "王" }
  }
}

wildcard

如果觉得prefix前缀查询还不能满足你的需求,那还可以考虑通配符查询。

{
  "query": {
      "wildcard": {
          "name": {
              "value": "王*五",
              "boost": 1.5
          }
      }
  }
}

wildcard支持2个通配符:

  1. ?表示匹配一个字符
  2. *匹配0到多个字符

boost的值可以影响相关性,小于1表示减小文档的相关性,大于1表示增加文档的相关性。

如果通配符还不满足需求,那还可以考虑regexp正则表达式查询

但是,强烈推荐线上环境只使用prefix,如果要希望影响评分相关性,那使用wildcard也不要以通配符开头。

constant_score

用时候我们只想过滤,就可以考虑constant_score查询:

{
  "query": {
    "bool": {
      "must": {
        "match_all": {}
      },
      "filter": {
        "term": {
          "status": 1
        }
      }
    }
  }
}

等价于:

{
  "query": {
    "constant_score": {
      "filter": {
        "term": {
          "status": 1
        }
      }
    }
  }
}

文档

查询与过滤上下文

结构化查询

bool查询

match

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
转载请注明出处: https://daima100.com/6749.html

(0)
上一篇 2023-04-04
下一篇 2023-04-04

相关推荐

  • Redis geohash 地理位置存储

    Redis geohash 地理位置存储Redis 的 GEO 特性将在 Redis 3.2 版本释出, 这个功能可以将用户给定的地理位置信息储存起来, 并对这些信息进行操作。 本文将对 Redis 的 GEO 特性进行介绍, 说明这个特…

    2023-01-25
    106
  • Python中dictionary.setdefault的使用方法

    Python中dictionary.setdefault的使用方法setdefault()函数是Python字典(Dictionary)中的一个函数,用于在字典中查找某个键,如果该键不存在,则返回一个默认值并插入到字典中。

    2024-03-19
    28
  • 使用Python和Tkinter创建动态GUI界面

    使用Python和Tkinter创建动态GUI界面Python是一门高级编程语言,主要用于面向对象、函数式和结构式编程。它已经成为了广泛使用的编程语言之一,被用于Web开发、数据分析、人工智能、机器学习等领域。Tkinter是Python的标准GUI库,包含了许多用于创建图形用户界面的工具和控件。在本文中,将介绍使用Python和Tkinter创建动态GUI界面的方法。

    2024-04-09
    23
  • 云三级架构_云数据中心架构

    云三级架构_云数据中心架构随着企业规模的扩大,对数据库可用性要求越来越高,更多企业采用两地三中心、异地多活的架构,以提高数据库的异常事件应对能力。 在数据库领域,我们常听的“两地三中心”、“异地多活”到底是什么呢? “两地三中

    2023-05-28
    92
  • Python中的断言: 定义及用法

    Python中的断言: 定义及用法在Python中,断言(assert)是一种用于调试的有效工具,它允许你核实某个条件是否为真,如果该条件不满足,就会抛出异常。

    2024-01-27
    68
  • 用Python实现二进制转换

    用Python实现二进制转换在计算机科学中,二进制是一种基于二的数字系统,只使用0和1两个数字进行运算,是计算机中数据存储和通信的基础。在计算机中,所有的数字、字母、符号等元素都是使用二进制进行表示的,因此对二进制进行转换是计算机编程中必不可少的操作。

    2024-02-16
    79
  • mysqlmha高可用_k8s高可用

    mysqlmha高可用_k8s高可用
    MHA: 对主节点进行监控,可实现自动故障转移至其他从节点; 通过提升某一从节点为新的主节点完成高可用; 环境准备: node7: 192.168.2.90…

    2023-04-08
    111
  • 初学Redis(五)–SpringBoot整合Redis+附项目代码「终于解决」

    初学Redis(五)–SpringBoot整合Redis+附项目代码「终于解决」1.环境搭建 我们还是继续用在初学Redis(四)中使用的项目 项目代码 链接:https://pan.baidu.com/s/1yiwBs1RZlD6D2jqc-qxUzQ 提取码:kzz3 1….

    2023-02-22
    101

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注