我有camp模型,该模型将日期存储在JSON领域中。我正在尝试优化数据库查询以检索未来日期的camp对象。

问题描述 投票:0回答:1
过滤了该模型的实例,其中没有一个日期等于或大于当前日期(基本上我只想要将来有一个日期的营)。我正在使用注释和子查询来从每个营地的日期获取“ max_date”,然后根据“ max_date”

过滤营地 我正在尝试优化此过滤过程,因为获取所有营地然后在Python中过滤它对于我的用例来说太慢了,并且随着更多的时间在必须过滤掉的营地数量上,这将继续增加。

我提出的解决方案为我提供了所需的结果,但是生成的SQL查询具有多个我不需要的子查询的多次运行。我想避免使用RAWSQL进行此操作,并想找到一种使用Django ORM函数实现所需结果的方法。我正在使用PostgreSQL,并且可以使用其提供的任何内置功能。
我使此功能获得了我需要的营地
def get_future_camps(): """ Retrieves all Camp objects where the latest date in the 'dates' JSONB field is today or in the future. Returns a QuerySet with only relevant fields. """ today_str = now().date().isoformat() camps_with_max = Camp.objects.annotate( max_date=Subquery( Camp.objects.filter( id=OuterRef("id") ).annotate( extracted_dates=JsonbArrayElementsText(F("dates")) ).values_list("extracted_dates", flat=True).order_by("-extracted_dates")[:1] ) ) return camps_with_max.filter( max_date__gte=today_str ).only("id", "pk")

# This only works for Postgres class JsonbArrayElementsText(Func): """ A custom function to extract elements from a JSONB array as text. """ function = 'jsonb_array_elements_text' output_field = CharField() this生成此SQL查询 SELECT "my_project_camp"."id", ( SELECT jsonb_array_elements_text(U0."dates") AS "extracted_dates" FROM "my_project_camp" U0 WHERE U0."id" = "my_project_camp"."id" ORDER BY 1 DESC LIMIT 1 ) AS "max_date" FROM "my_project_camp" WHERE ( SELECT jsonb_array_elements_text(U0."dates") AS "extracted_dates" FROM "my_project_camp" U0 WHERE U0."id" = "my_project_camp"."id" ORDER BY 1 DESC LIMIT 1 ) >= '''2025-03-08'''

该使用相同的子查询两次获得“ max_date”。查找之后,我发现在

WHERE

之前对

SELECT

子句进行了评估,因此您不能在

WHERE
子句中使用别名
我的问题是:有没有办法删除额外的子查询?我正在使用
only
,所以我不需要在过滤器本身之外使用max_date字段,而这样做的全部要点是优化获得未来的营地


我有camp模型,该模型存储在JSON领域中的一系列字符串。

Revisit
建模。
json blobs是一个好主意
[django-antipatterns]
如果您需要与斑点的一部分一起工作,这是违反了第一个正常形式(1nf)

[wiki]

[wiki]

python django django-models
1个回答
0
投票

与以下型号一起工作:

class Camp(models.Model): # no dates # … pass class CampDate(models.Model): camp = models.ForeignKey(Camp, on_delete=models.PROTECT) date = models.DateField()

也保证date是一个有效的日期,并将将此更紧凑存储在数据库中。 并检索: from django.utils.timezone import now today_str = now().date() Camp.objects.filter(campdate__date__gte=today_str).distinct()

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.