【问题标题】:Dynamic queries in Elasticsearch and issue of keywordsElasticsearch 中的动态查询和关键字问题
【发布时间】:2021-05-01 12:02:45
【问题描述】:

我目前遇到了一个问题,试图在Python 中为Elasticsearch 构建动态查询。为了进行查询,我使用来自elasticsearch_dslQ shortсut。这是我尝试实现的东西

...
s = Search(using=db, index="reestr")
condition = {"attr_1_":"value 1", "attr_2_":"value 2"} # try to build query from this
must = []
for key in condition:
    must.append(Q('match',key=condition[key]))

但这实际上导致了这种情况:

[Q('match',key="value 1"),Q('match',key="value 2")]

但是,我想要的是:

[Q('match',attr_1_="value 1"),Q('match',attr_2_="value 2")]

恕我直言,这个库进行查询的方式无效。我认为这种语法:

Q("match","attrubute_name"="attribute_value")

比这个更强大,可以做更多的事情:

Q("match",attribute_name="attribute_value")

看来,动态构建attribute_names似乎是不可能的。或者,当然,我可能不知道正确的方法。

【问题讨论】:

  • Q("match","attrubute_name"="attribute_value")Q("match",attribute_name="attribute_value") 之间的唯一区别是添加了引号。添加引号如何使其更强大或可以做更多事情?
  • 这不是关于引号,而是关于库如何解释参数的方式。如果我们可以动态构建它们(例如MongoDb 中没有问题),那么它将是更强大的工具。目前,我不知道如何为弹性构建动态查询。
  • 你试过阅读Elasticsearch documentation吗? Elasticsearch 的 RESTful API 非常强大(比 MongoDB 强大得多)并且可以轻松处理动态生成的查询。我不知道您使用什么 Python 库来与 ES 交互,但如果它有一些限制不能让您做您想做的事情,您可以考虑直接使用 RESTful API,或者尝试其他 Python 库。
  • 谢谢,我会检查的。至于库,我使用的是 elasticsearch_dsl。它极大地简化了编写查询的过程(与标准 es.search 等相比),但也有其细微差别,就像我在问题中提到的那样。
  • 好吧,其实我找到了解决方案 =) 解决方案是使用** 运算符,如下所示:Q('match',**{key:"value 2"}) 其中key 可以是变量

标签: python elasticsearch


【解决方案1】:

假设, 过滤器 = {'condition1':['value1'],'condition2':['value3','value4']}

代码:

    filters = data['filters_data'] 

    must_and = list() # The condition that has only one value
    should_or = list() # The condition that has more than 1 value

    for key in filters:
        if len(filters[key]) > 1:
            for item in filters[key]:
                should_or.append(Q("match", **{key:item})) 
        else:       
            must_and.append(Q("match", **{key:filters[key][0]})) 

    q1 = Bool(must=must_and)
    q2 = Bool(should=should_or)

    s = s.query(q1).query(q2) 
    result = s.execute()

也可以使用term,直接接受值列表,不需要复杂的for循环,

代码:

    for key in filters:
        must_and.append(Q("terms", **{key:filters[key]}))

    q1 = Bool(must=must_and)

【讨论】:

    猜你喜欢
    • 2011-06-01
    • 2019-09-18
    • 1970-01-01
    • 1970-01-01
    • 2014-03-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多