使用Python DSL在Elasticsearch中按天范围过滤数据



我写了下面这个方法来过滤最近8天的数据

def method_one(query) -> Query:
gte = (datetime.datetime.now() - datetime.timedelta(days=query)).date()
lt = (datetime.datetime.now()).date()
print(gte, lt)
return Q(MultiMatch(
query=filter("range", {"lastModifiedDate": {"gte": gte, "lt": lt}}
),
fields=['lastModifiedDate']
))

我想通过在Python中形成一个ElasticsearchQuery对象来过滤基于lastModifiedDate字段的数据。例如,如果我输入/lastModifiedDate=8(Rest API Call),它应该通过过滤返回最近8天的数据。

你不需要datetime模块在Elasticsearch中构造日期查询——你可以使用内置的日期数学:

from json import dumps
from elasticsearch_dsl.search import Search
from elasticsearch_dsl.query import Q, MultiMatch

def date_range_query(num_of_days):
if not isinstance(num_of_days, int):
raise Exception(
'expected numeric & positive `num_of_days`, got `%s`' % str(num_of_days))
return Q(
"range",
lastModifiedDate={
"gte": "now-%dd" % num_of_days,
"lt": "now"
}
)

try:
q = date_range_query(8)
print(dumps(q.to_dict(), indent=2))
except Exception as e:
print(e)

它会打印

{
"range": {
"lastModifiedDate": {
"gte": "now-8d",
"lt": "now"
}
}
}

或者如果坚持使用datetime.date对象,则需要首先对日期进行字符串化。现在,当您对str(...)这样做时,您实际上调用.__str()__,然后调用.isoformat()并返回格式化为YYYY-MM-DD的字符串。

现在,您的lastModifiedDate字段的映射可能具有不同的格式。因此,最好声明range查询的格式:

gte = (datetime.datetime.now() - datetime.timedelta(days=num_of_days)).date()
lt = (datetime.datetime.now()).date()
return Q(
"range",
lastModifiedDate={
"gte": str(gte),
"lt": str(lt),
"format": "yyyy-MM-dd"  # keep in mind that the format in ES conforms to Java syntax, not python
}
)

,它会产生类似的查询,但有具体的,详细说明的日期:

{
"range": {
"lastModifiedDate": {
"gte": "2021-02-26",
"lt": "2021-03-06",
"format": "yyyy-MM-dd"
}
}
}

最新更新