Python连接es笔记二之查询方式汇总

DevOps传教士
• 阅读 1200
本文首发于公众号:Hunter后端
原文链接:Python连接es笔记二之查询方式汇总

上一节除了介绍使用 Python 连接 es,还有最简单的 query() 方法,这一节介绍一下几种其他的查询方式。

以下是本篇笔记目录:

  1. query() 方法介绍
  2. Q() 查询
  3. 排序
  4. 分页
  5. source() 指定返回字段
  6. extra() 操作
  7. count() 总数
  8. from_dict() 函数

1、query() 方法介绍

在上一节中介绍了 query() 的一个简单示例,如下:

s = Search(using="default").index("exam")

s = s.query("match", name="张三丰")

query() 中接受两个参数,第一个是字段查询的方式,比如这里是 match,也可以是 term,这个依照查询的目的来替换。

第二个则是查询的字段与值,比如这里是查询的 name 字段为 "张三丰" 的数据。

如果是有多个条件,比如 name="张三丰",address="中国" 的数据,这里的 = ,并非是完全等于的意思,而是会依照前面的查询方式,比如 match 或 term 进行类似的分词或者模糊搜索。

如果是上面多个条件的查询,可以直接在后面加上类似的 query():

s = s.query("match", name="张三丰").query("match", address="中国")

这两个 query() 通过链式操作连在一起转换成 es 语句就是使用 must 将多条件连接在一起,我们可以使用 to_dict() 方式来查看:

s.to_dict()

# {'query': {'bool': {'must': [{'match': {'name': '张三丰'}}, {'match': {'address': '中国'}}]}}}

2、Q() 查询

如果看过之前我写过的 Django 系列笔记,应该记得在 Django 里也有个 Q() 方法的查询,和这里的一样,也是用于条件的联合,与或非条件都可以实现。

引入方式如下:

from elasticsearch_dsl import Q

但是如果是在 Django 中使用 es 的连接,也是同样使用 Q() 方法,我们可以使用 as 来区分,这里我们对于 es 的 Q() 方法可以使用 ES_Q() 来区分:

from elasticsearch_dsl import Q as ES_Q

单个条件的使用 Q() 如下:

s = s.query(ES_Q("match", name="张三丰"))

如下使用 dict 形式的操作也是等效的:

s = s.query(ES_Q({"match": {"name": "张三丰"}}))

与操作

对于这两个条件,如果想要实现它们的与操作:

q1 = ES_Q("match", name="张三丰")
q2 = ES_Q("match", address="中国")

可以如下实现:

s = s.query(q1 & q2)

或操作

如果是想实现上面的或操作,可以如下:

s = s.query(q1 | q2)

非操作

如果是想取反,直接在条件前加一个 ~ 即可:

q1 = ~ES_Q("match", name="张三丰")
s = s.query(q1)

multi_match

如果是搜索多字段,可以如下操作:

q = ES_Q("multi_match", query="中国 张三丰", fields=["name", "address"])

s = s.query(q)

text.keyword 操作

对于 es 中 text 字段,前面我们介绍过 .keyword 的查询方式,是将 text 字段作为一个整体进行查询,在 ES_Q() 中,以下两种操作是等效的:

q = ES_Q({"term": {"address.keyword": "中国湖北省"}})

q = ES_Q("term", address__keyword="中国湖北省")

filter() 操作

在 es 中的 filter 操作,在 Python 中是一个 filter() 函数,可以直接使用:

q = ES_Q("term", name="张三丰")
s = s.filter(q)

range 操作

实现大小于的操作示例如下:

q = ES_Q({"range": {"age": {"gte": 21}}})
s = s.query(q)

exclude() 操作

如果是想取反,除了使用 ~Q(),还可以直接使用 exclude() 函数,这个和 Django 里的操作也是一样的:

q = ES_Q("term", name="张三丰")
s = s.exclude(q)

3、排序

如果是想对返回的结果进行排序操作,直接使用 .sort() 方法。

比如想对 age 字段排序,正序返回数据,可如下操作:

s = s.sort("age")

如果是想倒序返回,可以如下操作:

s = s.sort("-age")

多字段排序直接在后面跟上就行:

s = s.sort("-age", "name")

4、分页

Python 连接 es 进行分页,可以直接使用 Python 里的切片操作,比如:

s = s[5:10]

5、source() 指定返回字段

我们可以通过 source() 方法指定返回的字段:

s = s.source(["name", "address"])

source() 方法还可以接受 includes 和 excludes 参数来指定返回的字段或者不返回的字段,这个和 es 的原生处理方式是一致的:

s = s.source(
    includes=["address"],
    excludes=["name"]
)

6、extra() 操作

extra() 函数接受一些查询的额外属性,比如 size 参数决定返回条数,比如 from 参数可以决定从第几条数据开始返回,sort 参数决定排序方式,以及 _source 参数决定返回的字段。

比如我们想要返回的数据从第 2 条数据开始,返回两条,按照 name 字段进行排序,只返回 name 和 _id 字段,可以如下操作:

s = Search(using="default").index("exam")
s = s.extra(
    sort="name",
    _source=["name"],
    **{
        "from": 1,
        "size": 2
    }
)
response = s.execute()

7、count() 总数

前面介绍过获取符合条件的总数,可以通过 response.hits.total.value 的方式获得,其实对于 Search(),可以直接使用 count() 函数:

count = s.count()

8、from_dict() 函数

如果我们想直接运行 kibana 里执行的命令,可以使用 from_dict() 函数,比如:

s = s.from_dict(
  {
    "query": {
      "term": {
        "name": {
          "value": "张三丰"
        }
      }
    }
  }
)

如果想获取更多后端相关文章,可扫码关注阅读:

Python连接es笔记二之查询方式汇总

点赞
收藏
评论区
推荐文章
blmius blmius
4年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
美凌格栋栋酱 美凌格栋栋酱
7个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Wesley13 Wesley13
3年前
FLV文件格式
1.        FLV文件对齐方式FLV文件以大端对齐方式存放多字节整型。如存放数字无符号16位的数字300(0x012C),那么在FLV文件中存放的顺序是:|0x01|0x2C|。如果是无符号32位数字300(0x0000012C),那么在FLV文件中的存放顺序是:|0x00|0x00|0x00|0x01|0x2C。2.  
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
PHP创建多级树型结构
<!lang:php<?php$areaarray(array('id'1,'pid'0,'name''中国'),array('id'5,'pid'0,'name''美国'),array('id'2,'pid'1,'name''吉林'),array('id'4,'pid'2,'n
Wesley13 Wesley13
3年前
Java日期时间API系列36
  十二时辰,古代劳动人民把一昼夜划分成十二个时段,每一个时段叫一个时辰。二十四小时和十二时辰对照表:时辰时间24时制子时深夜11:00凌晨01:0023:0001:00丑时上午01:00上午03:0001:0003:00寅时上午03:00上午0
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Python进阶者 Python进阶者
1年前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这
DevOps传教士
DevOps传教士
Lv1
夜闻归雁生乡思,病入新年感物华。
文章
4
粉丝
0
获赞
0