Django查询根据属性

时间:2015-04-25 06:33:31

标签: django django-queryset set-theory

我的模型如下:

class Item(models.Model):
    VENDOR_CHOICES = (
        ('a', 'A'),
        ('b', 'B')
    )

    vendor = models.CharField(max_length=16, choices=VENDOR_CHOICES)
    name = models.CharField(max_length=255)
    price = models.DecimalField(max_digits=6, decimal_places=2)

现在我有2个数据源,因此我从供应商A获得了项目,从供应商B获得了项目。

在某些情况下,供应商A可能与供应商B不具有相同的项目,例如供应商A有30个项目,供应商B有442个项目,其中只有6个项目是常见的。常见的项目被定义为具有完全相同名称的项目。

我还需要找到供应商a和供应商b项共有的商品价格差异,这意味着供应商a和供应商b中具有相同名称的商品。我有一个很大的没有。对于每个供应商可能达到10k项目的项目,因此需要一种有效的方法吗?

2 个答案:

答案 0 :(得分:1)

我认为这样的事情应该有效:

vendor_a_items = Item.objects.filter(vendor='a')
vendor_b_items = Item.objects.filter(vendor='b')

common_items = vendor_a_items.filter(
                       name__in=vendor_b_items.values_list('name', flat=True))

更新:要查找价格差异,您只需循环查找找到的常用项目:

for a_item in common_items:
    b_item = vendor_b_items.get(name=a_item.name)
    print u'%s: %s' % (a_item.name, a_item.price - b_item.price)

这会为每个找到的项目添加数据库命中,但如果您有少量常用项目,那么此解决方案将正常工作。对于较大的交叉点,您可以在一个查询中加载vendor_b_items的所有价格。使用此代码代替上一个代码段。

common_items_d = {item.name: item for item in common_items}
for b_item in vendor_b_items.filter(name__in=common_items_d.keys()):
    print u'%s: %s' % (b_item.name,
                      common_items_d[b_item.name].price - b_item.price)

答案 1 :(得分:0)

django 1.11开始,可以使用内置的交集和差异方法解决此问题。

vendor_a_items = Item.objects.filter(vendor='a')
vendor_b_items = Item.objects.filter(vendor='b')
common_items = vendor_a_items.intersection(vendor_b_items)
vendor_a_exclussive_items = vendor_a_items.difference(vendor_b_items)
vendor_b_exclussive_items = vendor_b_items.difference(vendor_a_items)

有关更详细的用例,请参阅我的blog post