1

IN 句は遅いため (特に PostgreSQL では)、大きな IN 句を避けるのは良くないと読みました。

Fridge というクラスと、Vegetables and Condiments というクラスがあるとします。

これらは両方とも、それら自身と Fridge の間に ManyToMany 関係を持っています。

次のようなものです:

class Fridge(models.Model):
     condiments = models.ManyToManyField(Condiments)
     vegetables = models.ManyToManyField(Vegetables)

そして、ここに白い冷蔵庫を表す QuerySet があります。

qs = Fridges.objects.filter(color='white')

最初の質問:

「調味料 ID のリストが与えられたら、それらの調味料が入っているすべての冷蔵庫を取得してください (元の QuerySet を変更します)」。

2 番目のクエリ:

「野菜 ID のリストが与えられたら、それらの野菜がすべて入っているすべての冷蔵庫を取得します (元の QuerySet を変更します)。」

冷蔵庫 ID のリストを作成してクエリセットに IN 句を追加せずに、どうやってそれを行うのでしょうか?

IN句でそれを行うソリューションは次のとおりです(既存のソリューションの名前が変更されたバージョン):

最初のクエリ:

    condiment_ids = [...] # list of condiment IDs
    condiments = Condiment.objects.filter(
        id__in=condiment_ids).all()
    condiment_fridges = None
    for condiment in condiments:
        qs = condiment.fridge_set.all()
        if not condiment_fridges:
            condiment_fridges = qs
        else:
            condiment_fridges = condiment_fridges | qs
    qs = qs.filter(id__in=[l.id for l in condiment_fridges])

2 番目のクエリ:

    vegetable_ids = [...] # list of vegetable IDs
    vegetables = vegetable.objects.filter(id__in=vegetable_ids).all()
    vegetable_fridges = None
    for vegetable in vegetables:
        qs = vegetable.location_set.all()
        if not vegetable_fridges:
            vegetable_fridges = qs
        else:
            vegetable_fridges = vegetable_fridges & qs
    qs = qs.filter(id__in=[l.id for l in vegetable_fridges])

これらのソリューションは恐ろしくハックに思えます.DjangoのORMでそれらを行うより良い方法があるかどうか疑問に思っていました.

4

1 に答える 1

1

私が質問を誤解していない限り、必要なのは次のとおりです。

Fridge.objects.filter(condiments__in=[1,2,3,4,5])

冷蔵庫にすべての調味料が入っているかどうかを調べるもっと効率的な方法があるかもしれません。テストされていませんが、次のようなものです:

max_conds = Condiment.objects.all().count()
result = Fridge.objects.annotate(conds=Count('condiments')).filter(conds=max_conds)

データベースバックエンドと各モデルの行数によっては、遅くなる可能性があります。

于 2012-06-07T19:21:55.247 に答える