Django ORM - 用另一个子查询注释查询,同时保留子查询的结果
Django ORM - Annotate Query with another SubQuery while keeping the results of SubQuery
# My Database Models
ModelA(models.Model):
referancer = models.CharField()
...
ModelXYZ(models.Model):
name = models.CharField()
...
我有像 top 这样的模型,它们之间没有外键关系,结构也应该保持这种方式,因为在我的真实查询中;过滤器和注释比这个更复杂。这也是重现问题的最简单方法。
modelXYZ_subquery = ModelXYZ.objects.filter(name__exact=OuterRef('referancer')).order_by('-id')
modelA_dataset = ModelA.objects.filter(**my_custom_filters).annotate(
has_XYZ=Exists(modelXYZ_subquery),
latest_xyz=Subquery(modelXYZ_subquery.values('id')[:1], output_field=IntegerField)
)
for _modelA in modelA_dataset:
my_custom_function_1(_modelA)
if _modelA.has_XYZ:
detected_xyz = ModelXYZ.objects.get(id=_modelA.latest_xyz) # Database Hit
else:
detected_xyz = create_xyz(_modelA)
my_custom_function_2(_modelA, detected_xyz)
这是我得到的功能,但由于数据集庞大,它的工作时间太长了。
我想摆脱不必要的数据库命中 我在 for 循环中到达顶部。
是否可以通过 annotation 或 prefetch_related 或其他方式实现此目标?
可以考虑使用JoinField。这不会改变您的数据库结构,但会允许 ORM 以与外键相同的方式进行连接。 pip install django-joinfield
并在 settings.py
中将 joinfield
放入 INSTALLED_APPS
from joinfield.joinfield import JoinField
class ModelXYZ(models.Model):
name = JoinField(ModelA, to_field='referancer', on_delete=models.DO_NOTHING)
makemigrations 将创建迁移,但迁移不会更改您的数据库结构。 ModelXYZ.name 中允许 ModelA.referancer.
中不存在的值
现在您可以 prefetch_related
从 ModelA 到 ModelXYZ。
# My Database Models
ModelA(models.Model):
referancer = models.CharField()
...
ModelXYZ(models.Model):
name = models.CharField()
...
我有像 top 这样的模型,它们之间没有外键关系,结构也应该保持这种方式,因为在我的真实查询中;过滤器和注释比这个更复杂。这也是重现问题的最简单方法。
modelXYZ_subquery = ModelXYZ.objects.filter(name__exact=OuterRef('referancer')).order_by('-id')
modelA_dataset = ModelA.objects.filter(**my_custom_filters).annotate(
has_XYZ=Exists(modelXYZ_subquery),
latest_xyz=Subquery(modelXYZ_subquery.values('id')[:1], output_field=IntegerField)
)
for _modelA in modelA_dataset:
my_custom_function_1(_modelA)
if _modelA.has_XYZ:
detected_xyz = ModelXYZ.objects.get(id=_modelA.latest_xyz) # Database Hit
else:
detected_xyz = create_xyz(_modelA)
my_custom_function_2(_modelA, detected_xyz)
这是我得到的功能,但由于数据集庞大,它的工作时间太长了。
我想摆脱不必要的数据库命中 我在 for 循环中到达顶部。
是否可以通过 annotation 或 prefetch_related 或其他方式实现此目标?
可以考虑使用JoinField。这不会改变您的数据库结构,但会允许 ORM 以与外键相同的方式进行连接。 pip install django-joinfield
并在 settings.py
joinfield
放入 INSTALLED_APPS
from joinfield.joinfield import JoinField
class ModelXYZ(models.Model):
name = JoinField(ModelA, to_field='referancer', on_delete=models.DO_NOTHING)
makemigrations 将创建迁移,但迁移不会更改您的数据库结构。 ModelXYZ.name 中允许 ModelA.referancer.
中不存在的值现在您可以 prefetch_related
从 ModelA 到 ModelXYZ。