Django查询集优化 - 从一个表聚合,从另一个表聚合

时间:2017-05-24 15:11:54

标签: django query-optimization django-queryset

我们有一个键值数据存储区,由以下模型定义:

models.py

if (new Date() >= new Date(pdate+"T12:00Z"))
{
    //selected date is greater than or equals to current date. Good to do code.
}
else
{
    // ....
}

所以我想要实现的是获得给定的'Person'列表,这些程序至少提供一个结果并在程序级别进行计数。

目前,我所做的是以下内容:

#Table with millions of entries
class Person(models.Model):
    name = models.CharField()
    group = models.ForeignKey(Group) 

# Table with few entries
class Program(models.Model):
    name = models.CharField()

# Table with hundreds of entries
class ResultType(models.Model):
    name = models.CharField()
    type = models.CharField()

# Huge table with billions of entries
class Result(models.Model):
    person = models.ForeignKey(Person, related_name='gotten_results')
    program = models.ForeignKey(Program, related_name='given_results')
    result_type = models.ForeignKey(ResultType, related_name='type_results')
    value = models.CharField()

这是最简单的方法(2秒思考),但如果我的given_group包含一百万人,这是一种可怕的方法。

我想到的另一个解决方案是使用select_related / prefetch_related但是我无法想象如何将它们与exists()或LIMIT等效[:1]

一起使用

有没有人有一个很好的建议,以很少的请求获得相同的结果?

丹尼尔的回答让我走上正轨,所以这就是解决方案:

def my_function(given_group):
    persons = Person.objects.filter(group=given_group)
    programs = Program.objects.all()

    given_results = {}
    for program in programs :
        given_results[program.name] = 0

        for person in persons :
            # if the program gave at least one result to the person
            if Result.objects.filter(program=program, person=person).exists() :
                given_results[program.name] += 1
            else:
                continue

    return given_results

1 个答案:

答案 0 :(得分:0)

您根本不想查询相关表,因为您实际上并不想要数据。你想要的是一个计算值的聚合。所以:

{'program__name': 'foo', 'total': 100000}

它为您提供了df timeStamp 0 2014-01-02 21:03:04 1 2014-02-02 21:03:05 2 2016-02-04 18:03:10 形式的词条列表,但如果您需要的话,将其转换为单个词典则相当简单。