第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

Django:使用傳播數(shù)據(jù)優(yōu)化查詢

Django:使用傳播數(shù)據(jù)優(yōu)化查詢

胡說叔叔 2021-11-16 15:25:48
我有Order對象和OrderOperation對象代表對訂單的操作(創(chuàng)建、修改、取消)。從概念上講,一個訂單有一對多的訂單操作。每次對訂單進(jìn)行操作時,都會在此操作中計算總數(shù)。這意味著當(dāng)我需要找到一個訂單的總數(shù)時,我只得到最后一個訂單操作的總數(shù)。簡化的代碼class OrderOperation(models.Model):    order = models.ForeignKey(Order)    total = DecimalField(max_digits=9, decimal_places=2)class Order(models.Model):    @property    def last_operation(self) -> Optional['OrderOperation']:        try:            qs = self.orderoperation_set.all()            return qs[len(qs) - 1]        except AssertionError:  # when there is a negative indexing (no operation)            # IndexError can not happen            return None    @property    def total(self) -> Optional[Decimal]:        last_operation = self.last_operation        return last_operation.total if last_operation else None問題由于接到的訂單很多,每次想做“總低于5歐元的訂單”之類的簡單過濾,需要很長時間,因為要瀏覽所有訂單,使用如下,明顯不好查詢:all_objects = Order.objects.all()Order.objects.prefetch_related('orderoperation_set').filter(    pk__in=[o.pk for o in all_objects if o.total <= some_value])我目前的想法/我嘗試過的數(shù)據(jù)非規(guī)范化?我可以簡單地創(chuàng)建一個total屬性 on Order,并在每次創(chuàng)建操作時將操作總數(shù)復(fù)制到訂單總數(shù)中。然后,Order.objects.filter(total__lte=some_value)會工作。但是,在我的數(shù)據(jù)庫中復(fù)制數(shù)據(jù)之前,我想確保沒有更簡單/更清潔的解決方案。使用 annotate() 方法?不知何故,我希望能夠做到:Order.objects.annotate(total=something_magical_here).filter(total__lte=some_value)。好像是不可能的。單獨過濾然后匹配?order_operations = OrderOperation.objects.filter(total__lte=some_value)orders = Order.objects.filter(orderoperation__in=order_operations)這非???,但過濾很糟糕,因為我沒有過濾最后的操作,而是這里的所有操作。這是錯誤的。還有其他想法嗎?謝謝。
查看完整描述

1 回答

?
隔江千里

TA貢獻(xiàn)1906條經(jīng)驗 獲得超10個贊

使用 annotate() 方法

好像是不可能的。


當(dāng)然,這是可能的 ;) 您可以使用子查詢或一些巧妙的條件表達(dá)式。假設(shè)您想從上次訂單操作中獲取總金額,以下是子查詢示例:


from django.db.models import Subquery, OuterRef


orders = Order.objects.annotate(

    total=Subquery(                             # [1]

        OrderOperation.objects \

            .filter(order_id=OuterRef("pk")) \  # [2]

            .order_by('-id') \                  # [3]

            .values('total') \                  # [4]

            [:1]                                # [5]

    )

)

上面代碼的解釋:

  1. 我們正在向結(jié)果列表添加新字段,稱為totaltaht 將由子查詢填充。您可以Order將此查詢集中的任何其他模型字段訪問它(在評估它之后,在模型實例中或在過濾和其他注釋中)。您可以從Django 文檔中了解注釋的工作原理。

  2. 子查詢應(yīng)該只針對當(dāng)前訂單的操作調(diào)用。OuterRefjust 將被替換為對結(jié)果 SQL 查詢中選定字段的引用。

  3. 我們想按操作id降序排序,因為我們確實想要最新的。如果您的操作中有其他字段需要按順序排序(例如創(chuàng)建日期),請在此處填寫。

  4. 該子查詢應(yīng)該只total從操作返回值

  5. 我們只想要一個元素。它是使用切片符號而不是普通索引來獲取的,因為在 django 查詢集上使用索引將立即調(diào)用它。切片只是LIMIT向 SQL 查詢添加子句,而不調(diào)用它,這就是我們想要的。

現(xiàn)在您可以使用:

orders.filter(total__lte=some_value)

只獲取您想要的訂單。您還可以使用該注釋來


查看完整回答
反對 回復(fù) 2021-11-16
  • 1 回答
  • 0 關(guān)注
  • 151 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動學(xué)習(xí)伙伴

公眾號

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號