Elasticsearch
Elasticsearch DSL是一个高级库,旨在帮助针对Elasticsearch编写和运行查询。它基于官方的低级客户端(elasticsearch-py
)构建。
它提供了一种更方便,更惯用的方式来编写和操作查询。它与Elasticsearch JSON DSL保持紧密联系,反映了其术语和结构。它直接使用定义的类或类似查询集的表达式从Python公开了整个DSL。
它还提供了一个可选的包装器,用于将文档作为Python对象使用:定义映射,检索和保存文档,将文档数据包装在用户定义的类中。
要使用其他Elasticsearch API(例如集群运行状况),只需使用基础客户端。
兼容性
从那时起,该库与所有Elasticsearch版本兼容,2.x
但您 必须使用匹配的主要版本:
对于Elasticsearch 7.0及更高版本,使用库的主要版本7(7.x.y
)。
对于Elasticsearch 6.0及更高版本,请使用库的主要版本6(6.x.y
)。
对于Elasticsearch 5.0及更高版本,请使用5.x.y
该库的主要版本5()。
对于Elasticsearch 2.0及更高版本,请使用2.x.y
该库的主要版本2()。
在setup.py
或 requirements.txt
中设置需求的推荐方法是:
# Elasticsearch 7.x
elasticsearch-dsl>=7.0.0,<8.0.0
# Elasticsearch 6.x
elasticsearch-dsl>=6.0.0,<7.0.0
# Elasticsearch 5.x
elasticsearch-dsl>=5.0.0,<6.0.0
# Elasticsearch 2.x
elasticsearch-dsl>=2.0.0,<3.0.0
这里实验的环境是python3.7
pip3 install elasticsearch-dsl
#默认就是7.1.0
![](https://img.haomeiwen.com/i18766817/0ef817ba170559d5.png)
配置
详细的选择
---->官方文档
有几种方法可以配置库的连接。最简单,最有用的方法是定义一个默认连接,该连接可以在每次进行API调用时使用,而无需显式传递其他连接。
注意
除非您要从应用程序访问多个群集,否则强烈建议您使用该create_connection方法,并且所有操作都将自动使用该连接。
默认连接
要定义可全局使用的默认连接,请使用如下connections
模块和create_connection
方法:
from elasticsearch_dsl import connections
connections.create_connection(hosts=['localhost'], timeout=20)
具有别名的单连接
您可以定义alias
连接的或名称,以便以后轻松引用它。其缺省值alias
是default
。
from elasticsearch_dsl import connections
connections.create_connection(alias='my_new_connection', hosts=['localhost'], timeout=60)
额外的关键词参数(hosts
和timeout
在我们的例子)将被传递到Elasticsearch
从类elasticsearch-py
。
要查看所有可能的配置选项,请参考文档。
多个群集
您可以使用以下configure
方法同时定义到多个集群的多个连接:
from elasticsearch_dsl import connections
connections.configure(
default={'hosts': 'localhost'},
dev={
'hosts': ['esdev1.example.com:9200'],
'sniff_on_start': True
}
)
首次请求时,此类连接将延迟构建。
您也可以通过一个接一个地添加多个连接来定义多个连接,如以下示例所示:
# if you have configuration options to be passed to Elasticsearch.__init__
# this also shows creating a connection with the alias 'qa'
connections.create_connection('qa', hosts=['esqa1.example.com'], sniff_on_start=True)
# if you already have an Elasticsearch instance ready
connections.add_connection('another_qa', my_client)
使用别名
使用多个连接时,可以使用创建连接时指定的字符串别名来引用它们。
此示例显示如何对连接使用别名:
s = Search(using='qa')
KeyError
如果没有使用该别名注册的连接,则将引发A。
单一查询
from elasticsearch_dsl.connections import connections ##导入的模块
from elasticsearch_dsl import Search
es = connections.create_connection(hosts=['10.0.122.124']) ## 连接到装有ela的主机上
ser = Search(
using = es,
index = "yan-filebeat-7.4.2-2019.11.22").filter( #索引是ela中拥有的
"match" , response="200" #match是全部匹配 后面的是条件
).query(
"match" , clientip="123.244.101.255" # 接收的查询体语句
)
res = ser.execute() #使用execute方法将这个查询给提交到ela中
print(res)
print(ser.count())
##返回的是一个<Response: >对象 需要循环才能够得到
# for item in ser:
# print(item.age, item.name)
print(ser.to_dict())
#结果是将上面的过滤条件变成字典{'query': {'bool': {'filter': [{'match': {'response': '200'}}], 'must': [{'match': {'clientip': '123.244.101.255'}}]}}}
几个字段的意义
using
指明用那个已经连接的对象
query
接收的是查询体语句
exclude
接收的是不匹配的字段 就像 must_not
filter
接收的是过滤语句 ,过滤的条件意思是在返回结果中有这些条件的信息
Search DSL
该Search对象
该Search对象代表整个搜索请求:
- 查询(queries)
- 过滤器(filters)
- 聚合(aggregations)
- 排序(sort)
- 分页(pagination)
- 附加的参数(additional parameters)
- 关联客户端(associated client)
API 被设计为可链接的。除了聚合功能以外,这意味着Search对象是不可变的(对对象的所有更改都将导致创建(拷贝)一个包含更改的副本)。这意味着您可以安全地将Search对象传递给外部代码,而不必担心这个对象会被修改。
解读上面的代码
实例化对象时,您可以传递低级别的elasticsearch客户端实例Search:
from elasticsearch import Elasticsearch
from elasticsearch_dsl import Search
es = connections.create_connection(hosts=['10.0.122.124'])
ser = Search(using=es)
==所有的方法都会返回一个对象的副本,从而安全地传递给外部代码。==
API 是可连接的,允许你在一个语句中调用多个方法:
ser = Search(
using = es,
index = "yan-filebeat-7.4.2-2019.11.22").filter( #索引是ela中拥有的
"match" , response="200" #match是全部匹配 后面的是条件
).query(
"match" , clientip="123.244.101.255" # 接收的查询体语句
)
要将请求发送到Elasticsearch:
res = s.execute()
如果您只是想遍历搜索返回的匹配,则可以遍历该Search对象:
for item in ser:
print(item.age, item.name)
搜索结果将被缓存。随后调用execute或试图遍历已经执行的Search对象将不会触发额外的请求发送到Elasticsearch。强制请求时指定 ignore_cache=True调用execute。
这个 Search
的对象也可以转换为之前的Query DSL
格式
print(ser.to_dict())
-结果是将上面的过滤条件变成字典
-{'query': {'bool': {'filter': [{'match': {'response': '200'}}], 'must': [{'match': {'clientip': '123.244.101.255'}}]}}}
查询
Elasticsearch_dsl
的query
类为所有Elasticsearch
查询类型提供类。 传递所有参数作为关键字参数。 这些类接受任何关键字参数,然后dsl将传递给构造函数的所有参数作为结果字典中的顶级关键字序列化(因此生成的json
被发送到elasticsearch
)。 这意味着在DSL
中原始查询和其等价物之间存在明确的一对一映射:
查找一个query
匹配查询
from elasticsearch_dsl.query import MultiMatch, Match
m = Match(clientip={"query": "123.244.101.255"})
s = Search().query(m)
for item in s:
print(item.clientip)
---------------------结果
<Response: [<Hit(yan-filebeat-7.4.2-2019.11.22/pzv8kW4BVikGLAHTfsPH): {'log': {'file': {'path': '/2018.log'}, 'offset': 1130582}, ...}>, <Hit(yan-filebeat-7.4.2-2019.11.22/LG78kW4BASo8U20ckcuk): {'log': {'file': {'path': '/2018.log'}, 'offset': 2043601}, ...}>, <Hit(yan-filebeat-7.4.2-2019.11.22/M278kW4BASo8U20ckcuk): {'log': {'file': {'path': '/2018.log'}, 'offset': 2044830}, ...}>]>
3
{'query': {'bool': {'filter': [{'match': {'response': '200'}}], 'must': [{'match': {'clientip': '123.244.101.255'}}]}}}
123.244.101.255
123.244.101.255
123.244.101.255
查找多个query
multi_match 多匹配查询
from elasticsearch_dsl.query import MultiMatch, Match
mm = MultiMatch(
# 被搜索字段的内容
query="123.244.101.255",
# 被搜索的字典
fields=["clientip", 'timestamp'])
s = Search().query(mm)
for item in s:
print(item.clientip)
---------------------------结果
<Response: [<Hit(yan-filebeat-7.4.2-2019.11.22/pzv8kW4BVikGLAHTfsPH): {'log': {'file': {'path': '/2018.log'}, 'offset': 1130582}, ...}>, <Hit(yan-filebeat-7.4.2-2019.11.22/LG78kW4BASo8U20ckcuk): {'log': {'file': {'path': '/2018.log'}, 'offset': 2043601}, ...}>, <Hit(yan-filebeat-7.4.2-2019.11.22/M278kW4BASo8U20ckcuk): {'log': {'file': {'path': '/2018.log'}, 'offset': 2044830}, ...}>]>
3
{'query': {'bool': {'filter': [{'match': {'response': '200'}}], 'must': [{'match': {'clientip': '123.244.101.255'}}]}}}
123.244.101.255
123.244.101.255
123.244.101.255
==在某些情况下,由于python对标识符的限制,这种方法不支持字段中含有特殊字符的情况,比如:@timestamp。==
在这种情况下,你必须史使用原来的字典形式:Range(** {'@timestamp': {'lt': 'now'}})
强大的 Q
- 您可以使用Q快捷方式可以把带参数的名称或原始数据的dict构建成 Search 对应类的实例:
from elasticsearch_dsl import Q
q = Q("multi_match", query="123.244.101.255", fields=["clientip", 'timestamp'])
#使用Q查询的话请使用.query()的方法
s = Search().query(q)
当然
s = s.query("multi_match", query='123.244.101.255', fields=['clientip', 'timestamp']) 也支持
----------------------------
查找结果和上面的一样 就是可以使用Q将`multi_match`方法进行实例
用 Q 实现组合查询
Q 对象可以使用逻辑运算符进行组合:
q = Q("match", clientip="123.244.101.255") | Q("match", clientip="42.248.168.61")
----------------------------------------------------------------
Q("match", title='python') | Q("match", title='django')
# {"bool": {"should": [...]}}
# 匹配到任意条件即可
Q("match", title='python') & Q("match", title='django')
# {"bool": {"must": [...]}}
# 列表里的条件必须同时匹配
~Q("match", title="python")
# {"bool": {"must_not": [...]}}
# 非
排序
要指定排序顺序,请使用 .sort() 方法:
s = Search().sort(
'category',
'-title',
{"lines" : {"order" : "asc", "mode" : "avg"}}
)
==它接受可以是字符串或字典的位置参数。字符串值是一个字段名称,可以用-符号前缀来指定降序。==
恢复排序使用无参的 sort()
方法
s = s.sort()
分页
要指定from / size
参数,请使用Python切片AP
s = s[10:20]
# {"from": 10, "size": 10}
如果要访问与查询匹配的所有文档,可以使用 scan使用扫描/滚动弹性搜索API的方法
for hit in s.scan():
print(hit.title)
==请注意,在这种情况下,结果将不会被排序。==
网友评论