繁体   English   中英

根据模型字段限制查询集结果,有更好的方法吗?

[英]Limit queryset results based on model field, are there better ways?

基本上我想为每个主机获取最新的30个日志条目。 目前我在django-piston中这样做。

def read(self,request):
    val={}
    for x in Host.objects.all():
        val[x.uuid_id]=DataLog.objects.filter(host=x).order_by('-time')[:30]           
    return val

不幸的是,这个请求需要很长时间(目前大约10k数据库条目为1s)。 有更有效的方法吗?

哈珀

如果您使用PostgreSQL作为数据库后端并且不需要跨数据库兼容性,则可以使用功能强大的窗口函数来实现以下类似:

想象一下你的表看起来像那样:

CREATE TABLE x (
    i serial primary key,
    value integer not null,
    date timestamp,
    category text);

并且您想要每个类别的最新价值。 你会去做的 :

SELECT
    first_value(i) over w,
    first_value(value) over w,
    first_value(date) over w
    category,
FROM x
WINDOW w AS (PARTITION BY category ORDER BY date DESC);

您可以通过查询集管理器上的raw方法在django中使用这样的查询:

ModelX.objects.raw("""SELECT DISTINCT ....... FROM x WINDOW w .....""")

要按类别获取最后N个条目,查询会更复杂并涉及子查询:

SELECT i, value, date, category
FROM (SELECT
        i, value, date, category,
        row_number() over w
    FROM x
    WINDOW w AS (PARTITION BY category ORDER BY date DESC)) AS subquery
WHERE subquery.row_number <= 30;

看到这一点,你甚至可以看到一个观点:

CREATE VIEW x_with_reverse_date_index AS
    (SELECT
        i, value, date, category,
        row_number() over w
    FROM x
    WINDOW w AS (PARTITION BY category ORDER BY date DESC));

并创建一个查询此视图的django模型:

class ModelX(models.Model):
    ...
    ...
    row_number = models.IntegerField("Row number when ordering by date desc")

    class Meta:
        db_table = 'x_with_reverse_date_index'

并“正常”查询:

ModelX.objects.filter(category__in = ('catA','catB'), row_number__lte = 30)
ModelX.objects.filter(row_number = 29)
...

警告 :如果您需要适用于其他数据库引擎的代码,请不要这样做。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM