美文网首页
python3 使用Api 操作 Elasticsearch

python3 使用Api 操作 Elasticsearch

作者: _str_ | 来源:发表于2019-11-22 21:14 被阅读0次

    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对象代表整个搜索请求:

    • 查询(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_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

    • 您可以使用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)
    

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

    相关文章

      网友评论

          本文标题:python3 使用Api 操作 Elasticsearch

          本文链接:https://www.haomeiwen.com/subject/obnqwctx.html