Django queryset-按列上的和筛选/排除



对于小型缓存应用程序,我有以下问题:

模型的一部分:

class CachedResource(models.Model):
    ...
    filesize = models.PositiveIntegerField()
    created = models.DateTimeField(auto_now_add=True, editable=False)
    ...

缓存应限制在200MB以内,并保留最新的文件。

如何创建一个查询集,如:

CachedResource.objects.order_by('-created').exclude(" summary of filesize < x ")

感谢您的任何意见!

示例:

created             filesize        keep/delete?
2014-06-22 15:00          50        keep    (sum: 50)
2014-06-22 14:50         100        keep    (sum: 150)
2014-06-22 14:40          30        keep    (sum: 180)
2014-06-22 14:30          20        keep    (sum: 200)
2014-06-22 14:20          50        delete  (sum: 250 > 200)
2014-06-22 14:10          10        delete  ...
2014-06-22 14:00         200        delete  ...
2014-06-22 13:50          10        delete  ...
2014-06-22 13:40           2        delete  ...
             ...         ...        ...     ...

以下查询集中的每个对象都有一个"filesize_sum"属性,其中包含自该对象创建以来创建的所有缓存资源的文件大小摘要。

qs = CachedResource.objects.order_by('-created').extra(select={
  'filesize_sum': """
   SELECT
     SUM(filesize)
   FROM
     CachedResource_table_name as cr
   WHERE
     cr.created >= CachedResource_table_name.created
     """})

然后你可以做一个循环来做你想做的事。例如,您可以在文件大小sum>200MB的第一个对象上创建一个循环,并在查询集上为创建日期小于或等于该对象的所有对象运行删除查询:

for obj in qs:
   if obj.filesize_sum > 200:
       qs.filter(created__lte=obj.created).delete()
       break

不过请记住,在插入新的缓存资源之前,您可能还需要采取一些操作,这样新资源的文件大小就不会超过您的限制。例如,您可以使用以下命令运行上述过程:

limit = configured_limit - filesize_of_cache_resource_to_insert

可能有更好的方法:

cachedResources = CachedResource.objects.order_by('-created')
list_of_items = []
size_of_files = 0
for item in cachedResources:
    if size_of_files < 200:
        list_of_items.append(item.id)
    else
        break
cached_resources_by_size = CachedResource.objects.filter(id__in=list_of_items).order_by('-created')
totals = CachedResource.objects.values('id').aggregate(sum=Sum('filesize'), count=Count('id'))
num_to_keep = totals['count'] * min(MAX_FILESIZE / totals['sum'], 1)
while num_to_keep < totals['count']:
    new_sum = CachedResource.objects.filter(id__in=CachedResource.objects.order_by('-created')[:num_to_keep]).aggregate(sum=Sum('filesize'))
    # if <not acceptable approximation>:
    #    adjust approximation
    #    continue
    CachedResource.objects.order_by('-created')[num_to_keep:].delete()
    break

第1行中的聚合可以获得单个查询中的总文件大小和条目数。基于这些结果,很容易计算出要保留的条目的近似数量。你可以做一些额外的检查来断言这个近似值在一定的范围内(正如你所说的+/-20%(。然后,一个简单的order_by和一个切片将生成一个包含要删除的所有条目的查询集。

相关内容

  • 没有找到相关文章

最新更新