• 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})
    
  • 相关阅读:
    uva 10491 Cows and Cars
    uva 10910 Marks Distribution
    uva 11029 Leading and Trailing
    手算整数的平方根
    uva 10375 Choose and divide
    uva 10056 What is the Probability?
    uva 11027 Palindromic Permutation
    uva 10023 Square root
    Ural(Timus) 1081. Binary Lexicographic Sequence
    扩展欧几里得(求解线性方程)
  • 原文地址:https://www.cnblogs.com/shangwei/p/13448901.html
Copyright © 2020-2023  润新知