如何解决使用 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 中形成一个 Elasticsearch lastModifiedDate
对象来根据 Query
字段过滤数据。
例如,如果我给出 /lastModifiedDate=8(Rest API 调用),它应该通过过滤过去 8 天返回数据。
解决方法
您不需要 datetime
模块在 Elasticsearch 中构建日期查询——您可以使用 built-in date math:
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"
}
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。