如何在Elasticsearch中运行查询和过滤器的组合?

时间:2019-08-11 04:15:53

标签: django elasticsearch elasticsearch-dsl

我正在django的虚拟项目中使用elasticsearch进行实验。我正在尝试使用django-elasticsearch-dsl进行搜索。用户可以提供titlesummaryscore进行搜索。搜索应与用户提供的所有信息相匹配,但是如果用户未提供任何有关某物的信息,则应将其跳过。

我正在运行以下代码来搜索所有值。

client = Elasticsearch()

s = Search().using(client).query("match", title=title_value)\
    .query("match", summary=summary_value)\
    .filter('range', score={'gt': scorefrom_value, 'lte': scoreto_value})

当我具有所有字段的值时,搜索将正常工作,但是例如,如果我不希望为summary_value提供值,尽管我希望搜索将继续搜索其余的值,结果就是没有任何结果。

在用户不提供值的情况下,字段默认具有一些值吗?还是我应该如何处理?


更新1 我尝试使用以下内容,但是无论输入是否给出相同的结果,它都会每次返回。

s = Search(using=client)

if title:
    s.query("match", title=title)

if summary:
    s.query("match", summary=summary)


response = s.execute()

更新2 我可以使用to_dict()进行打印。
如果如下所示,则s为空

s = Search(using=client)
s.query("match", title=title)

如果是这样

s = Search(using=client).query("match", title=title)

然后它可以正常工作,但是如果我添加s.query("match", summary=summary)仍然没有任何作用。

3 个答案:

答案 0 :(得分:2)

您需要分配回s

if title:
    s = s.query("match", title=title)

if summary:
    s = s.query("match", summary=summary)

答案 1 :(得分:1)

我在Search example中看到django-elasticsearch-dsl可让您在搜索后应用聚合,因此...

如何“分段”搜索?我可以考虑以下情况:

#first, declare the Search object
s = Search(using=client, index="my-index")

#if parameter1 exists
if parameter1:
    s.filter("term", field1= parameter1)

#if parameter2 exists
if parameter2:
    s.query("match", field=parameter2)

对所有参数执行相同的操作(每个参数都使用所需的方法),因此只有存在的参数才会出现在查询中。最后,只需运行

response = s.execute()

一切都会按照您的要求进行:D

答案 2 :(得分:0)

我建议您使用Python ES Client。它使您可以管理与集群相关的多项事务:设置映射,运行状况检查,执行查询等。

在其方法.search()中,body参数是您正常发送查询的地方({“ query” ...})。检查Usage example

现在,对于您的特殊情况,您可以将查询模板存储在变量中。首先,假设您仅使用filter做一个“空查询”,就像:

query = {
    "query":{
        "bool":{
            "filter":[
            ]
        }
    }
}

现在,您可以从此处使用已有的参数构建查询。

这是:

#This would look a little messy, but it's useful ;)
#if parameter1 is not None or emtpy
#(change the if statement for your particular case)
if parameter1:
    query["query"]["bool"]["filter"].append({"term": {"field1": parameter1}})

对所有参数执行相同的操作(对于字符串,通常使用“ term”,对于范围使用“ range”),并在.search()的body参数中发送查询,该查询应该可以根据需要工作。

希望这会有所帮助! :D