Python 如何基于“优化排序”;最新;相关模型
假设我们有两个模型Python 如何基于“优化排序”;最新;相关模型,python,sql,django,django-models,Python,Sql,Django,Django Models,假设我们有两个模型 class Product(models.Model): """ A model representing a product in a website. Has new datapoints referencing this as a foreign key daily """ name = models.CharField(null=False, max_length=1024, default="To be Scraped") url = mod
class Product(models.Model):
""" A model representing a product in a website. Has new datapoints referencing this as a foreign key daily """
name = models.CharField(null=False, max_length=1024, default="To be Scraped")
url = models.URLField(null=False, blank=False, max_length=10000)
class DataPoint(models.Model):
""" A model representing a datapoint in a Product's timeline. A new one is created for every product daily """
product = models.ForeignKey(Product, null=False)
price = models.FloatField(null=False, default=0.0)
inventory_left = models.BigIntegerField(null=False, default=0)
inventory_sold = models.BigIntegerField(null=False, default=0)
date_created = models.DateField(auto_now_add=True)
def __unicode__(self):
return "%s - %s" % (self.product.name, self.inventory_sold)
目标是根据附加到产品的最新数据点的库存销售价值对产品查询集进行排序。以下是我目前掌握的情况:
products = Product.objects.all()
datapoints = DataPoint.objects.filter(product__in=products)
datapoints = list(datapoints.values("product__id", "inventory_sold", "date_created"))
products_d = {}
# Loop over the datapoints values array
for i in datapoints:
# If a datapoint for the product doesn't exist in the products_d, add the datapoint
if str(i["product__id"]) not in products_d.keys():
products_d[str(i["product__id"])] = {"inventory_sold": i["inventory_sold"], "date_created": i["date_created"]}
# Otherwise, if the current datapoint was created after the existing datapoint, overwrite the datapoint in products_d
else:
if products_d[str(i["product__id"])]["date_created"] < i["date_created"]:
products_d[str(i["product__id"])] = {"inventory_sold": i["inventory_sold"], "date_created": i["date_created"]}
# Sort the products queryset based on the value of inventory_sold in the products_d dictionary
products = sorted(products, key=lambda x: products_d.get(str(x.id), {}).get("inventory_sold", 0), reverse=True)
products=Product.objects.all()
datapoints=DataPoint.objects.filter(product\uu in=products)
数据点=列表(datapoints.values(“产品标识”、“存货售出”、“创建日期”))
产品_d={}
#循环数据点值数组
对于数据点中的i:
#如果产品中不存在该产品的数据点,请添加该数据点
如果str(i[“product\u id”])不在products\u d.keys()中:
产品[str(i[“产品id”])]={“已售出库存”:i[“已售出库存”],“创建日期”:i[“创建日期”]}
#否则,如果当前数据点是在现有数据点之后创建的,则覆盖产品中的数据点
其他:
如果产品[str(i[“产品id”])[“创建日期”]
这可以正常工作,但它的速度非常慢,产品和数据点的数量很高(500000~)。有没有更好的办法
另一方面(不重要),因为我找不到关于这方面的任何信息,看起来DataPoint模型的unicode方法也在进行不必要的SQL查询。这是Django模型传递到模板后的默认特性吗?我认为您可以使用此处注释最新数据点的值,然后在此基础上排序
根据这些文档中的示例,它将类似于:
from django.db.models import OuterRef, Subquery
newest = DataPoint.objects.filter(product=OuterRef('pk')).order_by('-date_created')
products = Product.objects.annotate(
newest_inventory_sold=Subquery(newest.values('inventory_sold')[:1])
).order_by('newest_inventory_sold')
对于侧点,为了避免输出数据点时的额外查询,您需要在原始查询中使用select_related
:
datapoints = DatePoint.objects.filter(...).select_related('product')
这将进行连接,以便获取产品名称不会导致新的数据库查找。我认为您可以使用here注释最新数据点的值,然后在此基础上排序
根据这些文档中的示例,它将类似于:
from django.db.models import OuterRef, Subquery
newest = DataPoint.objects.filter(product=OuterRef('pk')).order_by('-date_created')
products = Product.objects.annotate(
newest_inventory_sold=Subquery(newest.values('inventory_sold')[:1])
).order_by('newest_inventory_sold')
对于侧点,为了避免输出数据点时的额外查询,您需要在原始查询中使用select_related
:
datapoints = DatePoint.objects.filter(...).select_related('product')
这将进行连接,以便获取产品名称不会导致新的数据库查找。太好了!我之前曾尝试将annotate与Max结合使用,但这绝对是错误的选择。这非常有效。谢谢你的帮助!太好了!我之前曾尝试将annotate与Max结合使用,但这绝对是错误的选择。这非常有效。谢谢你的帮助!