【ES】基础查询与复合查询--Python教程

目录

一、基本查询

1. atch_all 查询

2. match 查询

3. multi_match 查询

4. range 查询

5. term 查询

6. terms 查询

7. exists 查询和 missing 查询

二、组合查询

1. bool以及接收的参数

2. 增加带过滤器(filtering)的查询

3. constant_score 查询

三、通过Python查询

1. 详细代码实现如下

2. 具体的一个query实例


一、基本查询

1. atch_all 查询

match_all 查询简单的匹配所有文档。在没有指定查询方式时,它是默认的查询:

{ "match_all": {}}

它经常与 filter 结合使用—​例如,检索收件箱里的所有邮件。所有邮件被认为具有相同的相关性,所以都将获得分值为 1 的中性 _score

2. match 查询

在任何字段上都可进行全文搜索、精确查询

如果你在一个全文字段上使用 match 查询,在执行查询前,它将用正确的分析器去分析查询字符串:

{ "match": { "tweet": "About Search" }}

如果在一个精确值的字段上使用它,例如数字、日期、布尔或者一个 not_analyzed 字符串字段,那么它将会精确匹配给定的值:

{ "match": { "age":    26           }}
{ "match": { "date":   "2014-09-01" }}
{ "match": { "public": true         }}
{ "match": { "tag":    "full_text"  }}

对于精确值的查询,你可能需要使用 filter 语句来取代 query,因为 filter 将会被缓存。

3. multi_match 查询

multi_match 查询可以在多个字段上执行相同的 match 查询:

{
    "multi_match": {
        "query":    "full text search",
        "fields":   [ "title", "body" ]
    }
}

4. range 查询

range 查询找出那些落在指定区间内的数字或者时间:

{
    "range": {
        "age": {
            "gte":  20,
            "lt":   30
        }
    }
}


# gt 大于

# gte 大于等于

# lt 小于

# lte 小于等于

5. term 查询

term 查询被用于精确值匹配,这些精确值可能是数字、时间、布尔或者那些 not_analyzed 的字符串:

{ "term": { "age":    26           }}
{ "term": { "date":   "2014-09-01" }}
{ "term": { "public": true         }}
{ "term": { "tag":    "full_text"  }}

term 查询对于输入的文本不 分析 ,所以它将给定的值进行精确查询。

6. terms 查询

terms 查询和 term 查询一样,但它允许你指定多值进行匹配。如果这个字段包含了指定值中的任何一个值,那么这个文档满足条件:

{ "terms": { "tag": [ "search", "full_text", "nosql" ] }}

和 term 查询一样,terms 查询对于输入的文本不分析。它查询那些精确匹配的值(包括在大小写、重音、空格等方面的差异)。

7. exists 查询和 missing 查询

exists 查询和 missing 查询被用于查找那些指定字段中有值 (exists) 或无值 (missing) 的文档。这与SQL中的 IS_NULL (missing) 和 NOT IS_NULL (exists) 在本质上具有共性:

{
    "exists":   {
        "field":    "title"
    }
}

这些查询经常用于某个字段有值的情况和某个字段缺值的情况。

二、组合查询

现实的查询需求需要在多个字段上查询多种多样的文本,并且根据一系列的标准来过滤。为了构建类似的高级查询,可以用 bool 查询来实现需求。这种查询将多查询组合在一起,成为自己想要的布尔查询。

1. bool以及接收的参数

must

  • 文档 必须 匹配这些条件才能被包含进来。

must_not

  • 文档 必须不 匹配这些条件才能被包含进来。

should

  • 如果满足这些语句中的任意语句,将增加 _score ,否则,无任何影响。它们主要用于修正每个文档的相关性得分。

filter

  • 必须 匹配,但它以不评分、过滤模式来进行。这些语句对评分没有贡献,只是根据过滤标准来排除或包含文档。

每一个子查询都独自地计算文档的相关性得分。一旦他们的得分被计算出来, bool 查询就将这些得分进行合并并且返回一个代表整个布尔操作的得分。

下面的查询用于查找 title 字段匹配 how to make millions 并且不被标识为 spam 的文档。那些被标识为 starred 或在2014之后的文档,将比另外那些文档拥有更高的排名。如果 两者 都满足,那么它排名将更高:

{
    "bool": {
        "must":     { "match": { "title": "how to make millions" }},
        "must_not": { "match": { "tag":   "spam" }},
        "should": [
            { "match": { "tag": "starred" }},
            { "range": { "date": { "gte": "2014-01-01" }}}
        ]
    }
}

如果没有 must 语句,那么至少需要能够匹配其中的一条 should 语句。但,如果存在至少一条 must 语句,则对 should 语句的匹配没有要求。

2. 增加带过滤器(filtering)的查询

如果不想因为文档的时间而影响得分,可以用 filter 语句来重写前面的例子:

{
    "bool": {
        "must":     { "match": { "title": "how to make millions" }},
        "must_not": { "match": { "tag":   "spam" }},
        "should": [
            { "match": { "tag": "starred" }}
        ],
        "filter": {
          "range": { "date": { "gte": "2014-01-01" }} 
        }
    }
}

# range 查询已经从 should 语句中移到 filter 语句

通过将 range 查询移到 filter 语句中,将它转成不评分的查询,将不再影响文档的相关性排名。由于它现在是一个不评分的查询,可以使用各种对 filter 查询有效的优化手段来提升性能。

所有查询都可以借鉴这种方式。将查询移到 bool 查询的 filter 语句中,这样它就自动的转成一个不评分的 filter 了。

如果需要通过多个不同的标准来过滤你的文档,bool 查询本身也可以被用做不评分的查询。简单地将它放置到 filter 语句中并在内部构建布尔逻辑:

{
    "bool": {
        "must":     { "match": { "title": "how to make millions" }},
        "must_not": { "match": { "tag":   "spam" }},
        "should": [
            { "match": { "tag": "starred" }}
        ],
        "filter": {
          "bool": { 
              "must": [
                  { "range": { "date": { "gte": "2014-01-01" }}},
                  { "range": { "price": { "lte": 29.99 }}}
              ],
              "must_not": [
                  { "term": { "category": "ebooks" }}
              ]
          }
        }
    }
}

# 将 bool 查询包裹在 filter 语句中,我们可以在过滤标准中增加布尔逻辑

通过混合布尔查询,我们可以在我们的查询请求中灵活地编写 scoring 和 filtering 查询逻辑。

3. constant_score 查询

尽管没有 bool 查询使用这么频繁,constant_score 查询也是你工具箱里有用的查询工具。它将一个不变的常量评分应用于所有匹配的文档。它被经常用于只需要执行一个 filter 而没有其它查询(例如,评分查询)的情况下。

可以使用它来取代只有 filter 语句的 bool 查询。在性能上是完全相同的,但对于提高查询简洁性和清晰度有很大帮助。

{
    "constant_score":   {
        "filter": {
            "term": { "category": "ebooks" } 
        }
    }
}

# term 查询被放置在 constant_score 中,转成不评分的 filter。这种方式可以用来取代只有 filter 语句的 bool 查询。

三、通过Python查询

1. 详细代码实现如下

import unittest
# 需要导入的es包
from elasticsearch import Elasticsearch


class Demo(unittest.TestCase):
    """
    定义一个基础测试类
    """

    def test_get_es(self):
        """
        连接es,获取一个es实体,用于后续查询
        :return:
        """
        host = '172.16.153.129:9200'
        username = 'elastic'
        password = '123456'
        es = Elasticsearch(
            host,
            # 认证信息
            http_auth=(username, password)
        )
        print(es.info())
        return es

    def test_get_es_res_by_quey(self):
        """
        连接es,获取一个es实体,通过query进行查询
        :return:
        """
        host = '172.16.153.129:9200'
        username = 'elastic'
        password = '123456'

        es = Elasticsearch(host, http_auth=(username, password))
        print(es.info())

        # 具体的query例子 在后面
        query = {
            'bool': {
                'must_not': {'match': {'message': 'M('}},
                'must': [
                    {'match': {'TransId': '06100021650016153'}},
                    {'range': {'@timestamp': {'gte': u'now-7d', 'lte': 'now'}}}
                ]
            }
        }

        res = es.search(
            index='logstash-2021.06.11',
            body={
                "query": query,
                "sort": [{"@timestamp": {"order": "desc"}}]})

        return res

2. 具体的一个query实例

query = {  # 请求体
            "query": {  # 关键字,把查询语句给 query
                "bool": {  # 关键字,表示使用 filter 查询,没有匹配度
                    "must": [  # 表示里面的条件必须匹配,多个匹配元素可以放在列表里
                        {
                            "match": {  # 关键字,表示需要匹配的元素
                                "TransId": '06100021650016153'  # TransId 是字段名, 06100021650016153 是此字段需要匹配到的值
                            }
                        },
                        {
                            "match": {
                                "Ds": '2021-06-11'
                            }
                        },
                        {
                            "match": {
                                "Gy": '2021020235'
                            }
                        }, ],
                    "must_not": {  # 关键字,表示查询的结果里必须不匹配里面的元素
                        "match": {  # 关键字
                            "message": "M("  # message 字段名,这个字段的值一般是查询到的结果内容体。这里的意思是,返回的结果里不能包含特殊字符 'M('
                        }
                    }
                }
            },

            # 下面是对返回的结果继续排序
            "sort": [{"@timestamp": {"order": "desc"}}],
            "from": 0,  # 从匹配到的结果中的第几条数据开始返回,值是匹配到的数据的下标,从 0 开始
            "size": 10  # 返回多少条数据
        }

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值