• Python Elasticsearch DSL 查询


    Python Elasticsearch DSL 使用简介

    连接 Es:

    import elasticsearch
    
    clinet = elasticsearch.Elasticsearch([{"host": "10.44.99.102", "port": 9200}])
    or
    clinet = Elasticsearch(["10.44.99.102:9200"])
    

    先看一下搜索,q 是指搜索内容,空格对 q 查询结果没有影响,size 指定个数,from_ 指定起始位置,filter_path 可以指定需要显示的数据,如本例中显示在最后的结果中的只有 _id 和 _type。

    res_3 = clinet .search(index="bank", q="Holmes", size=1, from_=1)
    res_4 = clinet .search(index="bank", q=" 39225    5686 ", size=1000, filter_path=["hits.hits._id", "hits.hits._type"])
    

    查询指定索引的所有数据:

    其中,index 指定索引,字符串表示一个索引;列表表示多个索引,如 index=["bank", "banner", "country"];正则形式表示符合条件的多个索引,如 index=["apple*"],表示以 apple 开头的全部索引。

    search 中同样可以指定具体 doc-type。

    from elasticsearch_dsl import Search
    s = Search(using=clinet,index="situation-event").execute()
    logging.warning(s.to_dict())    
    

    忽略不可用的

    from elasticsearch_dsl import Search
    s = Search(using=clinet,index="situation-event")
    s = s.params(ignore_unavailable=True)
    

    根据某个字段查询,可以多个查询条件叠加:

    s = Search(using=clinet, index="situation-event").query("match", event_type="002")
    s.query("match", event_title="aaa")
    logging.warning(s.execute().to_dict())
    

    多字段查询:

    from elasticsearch_dsl.query import MultiMatch
    
    multi_match = MultiMatch(query="aaa",fields=["event_type","event_title"])
    s = Search(using=clinet,index="situation-event").query(multi_match)
    s = s.execute()
    logging.warning(s.to_dict())
    

    还可以用 Q() 对象进行多字段查询,fields 是一个列表,query 为所要查询的值。

    q = Q("multi_match",query="aaa",fields=["event_type","event_title"])
    s = Search(using=clinet, index="situation-event").query(q)
    s = s.execute()
    logging.warning(s.to_dict())
    

    Q() 第一个参数是查询方法,还可以是 bool。

    q = Q("bool",must=[Q("match",event_type="002"),Q("match",event_title="aaa")])
    s = Search(using=clinet,index="situation-event").query(q)
    s = s.execute()
    logging.warning(s.to_dict())
    

    通过 Q() 进行组合查询,相当于上面查询的另一种写法。

    q = Q("match", event_type="002") | Q("match", event_type="003")
    s = Search(using=clinet,index="situation-event").query(q).execute()
    logging.warning(s.to_dict())
    # {"query": {"bool": {"should": [{"match": {"event_type": "002"}}, {"match": {"event_type": "003"}}]}}}
    
    q = Q("match", event_type="002") & Q("match", event_type="003")
    s = Search(using=clinet,index="situation-event").query(q)
    logging.warning(s.to_dict())
    # {"query": {"bool": {"must": [{"match": {"event_type": "002"}}, {"match": {"event_type": "003"}}]}}}
    
    q = ~Q("match", event_type="002")
    s = Search(using=clinet,index="situation-event").query(q).execute()
    logging.warning(s.to_dict())
    # {"query": {"bool": {"must_not": [{"match": {"event_type": "002"}}]}}}
    

    过滤,在此为范围过滤,range 是方法,timestamp 是所要查询的 field 名字,gte 为大于等于,lt 为小于,根据需要设定即可。

    关于 term 和 match 的区别,term 是精确匹配,match 会模糊化,会进行分词,返回匹配度分数,(term 如果查询小写字母的字符串,有大写会返回空即没有命中,match 则是不区分大小写都可以进行查询,返回结果也一样)

    # 范围查询
    s = Search(using=clinet, index="situation-event").filter("range", update_time={"gte": 0, "lt": time.time()}) 
        .query("match", event_type="003")
    logging.warning(s.to_dict())
    # 
    # 普通查询
    s = Search(using=clinet, index="situation-event").filter("terms", event_type=["002", "003"]).execute()
    logging.warning(s.to_dict())
    # {"query": {"bool": {"filter": [{"terms": {"event_type": ["002", "003"]}}]}}}
    

    其他写法

    s = Search(using=clinet, index="situation-event").filter("terms", event_type=["002", "003"])
    logging.warning(s.to_dict())
    # {"query": {"bool": {"filter": [{"terms": {"event_type": ["002", "003"]}}]}}}
    
    s = Search(using=clinet, index="situation-event").query("bool", filter=[Q("terms", event_type=["002", "003"])])
    logging.warning(s.to_dict())
    # {"query": {"bool": {"filter": [{"terms": {"event_type": ["002", "003"]}}]}}}
    
    s = Search(using=clinet, index="situation-event").query("bool", filter=[~Q("terms", event_type=["002", "003"])])
    logging.warning(s.to_dict())
    # {"query": {"bool": {"filter": [{"bool": {"must_not": [{"terms": {"event_type": ["002", "003"]}}]}}]}}}
    

    聚合可以放在查询,过滤等操作的后面叠加,需要加 aggs。

    bucket 即为分组,其中第一个参数是分组的名字,自己指定即可,第二个参数是方法,第三个是指定的 field。

    metric 也是同样,metric 的方法有 sum、avg、max、min 等,但是需要指出的是,有两个方法可以一次性返回这些值,stats 和 extended_stats,后者还可以返回方差等值。

    # 单层聚合
    s = Search(using=clinet, index="situation-event")
    s.aggs.bucket("per_one","terms",field="event_type")
    res = s.execute()
    logging.warning(res.to_dict())
    # {"query": {"match_all": {}}, "aggs": {"per_one": {"terms": {"field": "event_type"}}}}
    
    #双层聚合
    s = Search(using=clinet, index="situation-event")
    s.aggs.bucket("per_one", "terms", field="event_type").bucket("per_two", "terms", field="event_level")
    res = s.execute()
    logging.warning(res.to_dict())
    # {"query": {"match_all": {}}, "aggs": {"per_one": {"terms": {"field": "event_type"}, "aggs": {"per_two": {"terms": {"field": "event_level"}}}}}}
    
    # 单层聚合
    s = Search(using=clinet,index="situation-event")
    s.aggs.metric("sum_system_id","stats",field="system_id")
    res = s.execute()
    logging.warning(res.to_dict())
    # {"query": {"match_all": {}}, "aggs": {"sum_system_id": {"stats": {"field": "system_id"}}}}
    
    # 双层聚合
    s = Search(using=clinet,index="situation-event")
    s.aggs.bucket("pre_one","terms",field="system_id").metric("sum_system_id","stats",field="system_id")
    res = s.execute()
    logging.warning(res.to_dict())
    # {"query": {"match_all": {}}, "aggs": {"pre_one": {"terms": {"field": "system_id"}, "aggs": {"sum_system_id": {"stats": {"field": "system_id"}}}}}}
    
    

    最后依然要执行 execute(),此处需要注意,s.aggs 操作不能用变量接收(如 res=s.aggs,这个操作是错误的),聚合的结果会保存到 res 中显示。

    排序

    s = Search().sort(
        "category",
        "-title",
        {"lines" : {"order" : "asc", "mode" : "avg"}}
    )
    

    分页

    s = s[10:20]
    # {"from": 10, "size": 10}
    

    一些扩展方法,感兴趣的同学可以看看:

    s = Search()
    
    # 设置扩展属性使用`.extra()`方法
    s = s.extra(explain=True)
    
    # 设置参数使用`.params()`
    s = s.params(search_type="count")
    
    # 如要要限制返回字段,可以使用`source()`方法
    # only return the selected fields
    s = s.source(["title", "body"])
    # don"t return any fields, just the metadata
    s = s.source(False)
    # explicitly include/exclude fields
    s = s.source(include=["title"], exclude=["user.*"])
    # reset the field selection
    s = s.source(None)
    
    # 使用dict序列化一个查询
    s = Search.from_dict({"query": {"match": {"title": "python"}}})
    
    # 修改已经存在的查询
    s.update_from_dict({"query": {"match": {"title": "python"}}, "size": 42})
    
  • 相关阅读:
    spring-cloud Feign
    spring-cloud eureka注册发现
    spring-cloud zuul网关
    正则表达式整理
    nginx配置-Rewrite
    nginx配置-main
    nginx用途
    Java命令行命令
    Task
    JavaScript难点整理
  • 原文地址:https://www.cnblogs.com/shangwei/p/13448901.html
Copyright © 2020-2023  润新知