【问题标题】:How to optimize DRF number queries when using properties in serializers fields?在序列化器字段中使用属性时如何优化 DRF 编号查询?
【发布时间】:2023-03-19 17:55:01
【问题描述】:

我正在开发一个 DRF API,但我并不完全熟悉 django 属性。

数据库关系是经典的。公司有不同的职位可供候选人申请。每个职位都有多个匹配项,匹配项是职位和候选人之间的连接表。匹配具有不同的状态,代表申请流程的不同阶段。

所以这里是交易: 我正在使用 drf 视图集从 api 获取数据。此视图集使用序列化程序来获取特定字段,特别是作业的每个状态的匹配数。序列化程序的简化版本如下所示。

class Team2AmBackofficeSerializer(Normal2JobSerializer):

    class Meta:
        model = Job
        fields = (    
            'pk',
            'name',
            'company',
            'company_name',
            'job__nb_matches_proposition',
            'job__nb_matches_preselection',
            'job__nb_matches_valides',
            'job__nb_matches_pitches',
            'job__nb_matches_entretiens',
            'job__nb_matches_offre',
        )

job__xxx 字段使用装饰器@property,例如:

@property
def job__nb_matches_offre(self):
    return self.matches.filter(current_status__step_name='Offre').count()

问题是每次我将这些属性之一添加到我的序列化程序的字段时,数据库查询的数量都会显着增加。这当然是因为每个属性都会多次调用数据库。所以这是我的问题:

有没有办法优化对数据库的查询次数,或者通过更改序列化程序中的某些内容,或者通过以不同方式获取特定状态的匹配次数? p>

我看过select_relatedprefetch_related。这让我在获取有关公司的信息时减少了查询次数,但实际上并没有减少匹配次数。

非常感谢任何帮助:)

【问题讨论】:

  • 您可以使用 annotate 执行一些技巧来预取这些信息(例如),但是您的查询仍然会很大。将这些字段随意创建到模型中,并在创建/编辑/删除时更新它(或者如果不需要即时准确性,则在异步任务中)是否可以接受?它肯定会更高效。

标签: python django django-rest-framework properties django-serializer


【解决方案1】:

您想要的是annotate 您的查询集使用这些值,这将导致数据库在一个查询中完成所有计数。结果明显快于您当前的解决方案。

例子:

from django.db.models import Count, Q

Job.objects.annotate(
    'nb_matches_offre'=Count(
        'pk',
        filter=Q(current_status__step_name='Offre')
    ),
    'nb_matches_entretiens'=Count(...)
).all()

生成的查询集将包含具有属性 job_obj.nb_matches_offrejob_obj.nb_matches_entretiens 的 Job 对象以及计数。

另见https://docs.djangoproject.com/en/3.0/topics/db/aggregation/

【讨论】:

  • 非常感谢!这就是我需要的。我只需要进行一些小的语法更改即可使其正常工作。这是它最终的样子:nb_matches_offre = Sum(Case(When(matches__current_status__step_name='Offre', then=1), default=0, output_field=IntegerField()))
  • @AntoineQuellier 很高兴听到。我没有测试我的代码 sn-p,我只是查看了我的代码中的内容并对其进行了简化和调整。它实际上可能需要一个子查询来使 Count 工作。但是您的解决方案听起来也不错。如果您担心数据库的性能,您可以从 postgres 日志文件中提取数据库查询并在 psql 中使用“分析解释”运行它。
猜你喜欢
  • 2021-03-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-16
  • 1970-01-01
  • 1970-01-01
  • 2018-09-21
  • 2021-05-08
相关资源
最近更新 更多