我尝试过不同的查询数据的方法,但仍会导致数据库大量ping。
我尝试过使用select_related
。
以下是我的模特:
class Order(models.Model):
num = models.CharField(max_length=50, unique=True)
class OrderInfo(models.Model):
info = models.CharField(max_length=100, unique=True)
datetime = models.DateTimeField(auto_now_add=True, blank=True)
order_fk = models.ForeignKey(Order)
我想要实现的目标:
OrderInfo
包含大量与Order
相关的信息。
我想要的是能够从数据库中获取最新的OrderInfo
,但我希望它对Order
是唯一的。独特的部分是我努力减少查询量的地方。
ois = OrderInfo.objects.order_by('-datetime').select_related('order_fk')
当我尝试过滤时,它会对每个订单进行查询,以检查查询的唯一性。
For instances:
_ = [oi.order_fk for oi in ois] # queries reach to 20k, takes too long.
此外,我只需要限制我得到的响应数量,但我需要先知道有多少唯一Orders
才能限制它。
任何人都知道一种最小化这些查询的正确方法,或者我可能需要重构我的模型。
注意:
答案 0 :(得分:1)
每个订单有多少OrderInfo
个对象?如果它很小,最简单的方法是使用prefetch_related
并在python中进行过滤:
class Order(models.Model):
num = models.CharField(max_length=50, unique=True)
@property
def latest_order_info(self):
return max(self.orderinfo_set.all(), key=attrgetter('datetime')
然后在您的应用程序代码中,您可以执行以下操作:
orders = Order.objects.filter(...).prefetch_related('orderinfo_set')
这有点浪费,但根据我的经验,除非父模型有很多孩子,否则通常不会成为瓶颈。
答案 1 :(得分:0)
基于this stack overflow answer to a similar question,我认为您只需要将其拆分为两个查询,以期减少与数据库挂钩的数量。
由于您使用的是SQLite,因此您无法访问DISTINCT ON
,因此请尝试以下操作:
from django.db.models import Q, Max
import operator
ois = OrderInfo.objects.values('order_id').annotate(max_datetime=Max('datetime'))
filters = reduce(operator.or_, [(Q(order_id=oi['order_id']) &
Q(datetime=oi['max_datetime'])) for oi in ois])
filtered_ois = OrderInfo.objects.filter(filters)
解释这是做什么的(再次,这是基于链接的堆栈溢出答案):
order_id
分组的OrderInfo对象,并在具有该OrderInfo
的所有order_id
个对象中注释具有最大日期时间的对象。OrderInfo
对象上创建新过滤器。OrderInfo
个对象上使用过滤器并将其返回。