python3 使用Api 操作 Elasticsearch

2019-11-22  本文已影响0人  _str_

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.pyrequirements.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
image.png

配置

详细的选择---->官方文档

有几种方法可以配置库的连接。最简单,最有用的方法是定义一个默认连接,该连接可以在每次进行API调用时使用,而无需显式传递其他连接。

注意
除非您要从应用程序访问多个群集,否则强烈建议您使用该create_connection方法,并且所有操作都将自动使用该连接。

默认连接

要定义可全局使用的默认连接,请使用如下connections模块和create_connection方法:

from elasticsearch_dsl import connections

connections.create_connection(hosts=['localhost'], timeout=20)

具有别名的单连接

您可以定义alias连接的或名称,以便以后轻松引用它。其缺省值aliasdefault

from elasticsearch_dsl import connections

connections.create_connection(alias='my_new_connection', hosts=['localhost'], timeout=60)

额外的关键词参数(hoststimeout在我们的例子)将被传递到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对象代表整个搜索请求:

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_dslquery类为所有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

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)

==请注意,在这种情况下,结果将不会被排序。==

上一篇下一篇

猜你喜欢

热点阅读