2

我对 Python 比较陌生,想知道是否可以在返回结果之前访问 Johnny Cache 缓存的结果以进行进一步处理,例如在其上运行进一步查询。

举个简单的例子,假设我们有一个包含数十万运动结果的表格,每个运动结果都按运动分类,例如网球、足球、高尔夫等。有些用户只对足球和高尔夫感兴趣,所以目前我们使用 johnny 缓存来缓存每个运动类别的查询结果 30 分钟。但是,我们不能将这些数据按原样传递给用户,因为它需要进一步过滤用户的偏好(例如,他们只想要某些球队/球员的结果)。对类别和用户偏好进行 db 调用会令人望而却步,这就是为什么我们缓存构成所有请求基础的查询部分(运动类别),但现在想要进一步过滤内存中的缓存以供用户使用偏好 - 这可以用 Johnny Cache 来完成吗?如果可以,请问怎么做?

4

1 回答 1

5

简短的回答是肯定的,但是您将无法在不引起另一个数据库调用的情况下使用 QuerySet 过滤器。您需要遍历返回的结果以避免数据库命中。这取决于您是否要根据返回结果的大小和新过滤查询的查询时间来执行此操作。

QuerySet文档中所述,过滤后的 QuerySet 返回一个不受原始 QuerySet 约束的新 QuerySet

要进一步了解情况,您可以查看信号johnny.signals.qc_hitjohnny.signals.qc_miss查看它何时进行数据库调用。 信号是一种将回调绑定到某些事件的 django 机制。在这种情况下,Johnny Cache 暴露了这两个有用的信号。

我创建了一个简单的应用程序来测试它并帮助演示这种行为。

模型.py

from django.db import models

class TestModel(models.Model):
    prop_a = models.TextField()
    prop_b = models.TextField()

    def __unicode__(self):
        return "{} {}".format(self.prop_a, self.prop_b)

视图.py

from django.dispatch import receiver
from django.http import HttpResponse

from johnny.signals import qc_hit, qc_miss
from models import TestModel

def index(self):
    objs = TestModel.objects.all()
    print objs
    print objs.filter(prop_a='a') #Causes another database or cache hit
    return HttpResponse("success")

def generate(self):
    generate_data()
    return HttpResponse("generated")

def generate_data():
    properties = [ 'a', 'b', 'c', 'd', 'e']
    for i in xrange(len(properties)):
        for j in xrange(len(properties)):
            test_model = TestModel(prop_a=properties[i], prop_b=properties[j])
            test_model.save()

@receiver(qc_hit)
def cache_hit(sender, **kwargs):
    print "cache hit"

@receiver(qc_miss)
def cache_miss(sender, **kwargs):
    print "cache miss"

由于 Johnny Cache 是通过中间件完成的,因此您需要通过视图对其进行测试,因为它从请求到响应都会发生。在上面的例子中,我们有一个非常简单的模型,我们正在查看所有TestModel对象,然后是过滤结果。输出将显示每一个最初导致缓存未命中,然后是缓存命中。它们不相关,被视为两个单独的查询。

但是,如果你做类似的事情

objs = TestModel.objects.all()
result = []
for obj in objs:
   if obj.prop_a == 'a':
      result.append(obj)

您只会看到对数据库/johnny 缓存的一次命中。显然,这会得到您想要的结果,但可能会或可能不会比另一个查询慢,具体取决于初始查询的大小。

我希望这有助于回答您的问题,并为您提供一种了解缓存如何进一步工作的方法。

于 2013-11-01T17:01:54.723 回答