2

TLDR django の queryset API のメソッドのwhereパラメーターをextra使用すると、クエリに追加されるカスタム SQL を挿入できANDます。ORクエリのリセットでその値を編集する必要がある状況があります。これに対するサポートはありますか?


別のテーブルとの M2M 関係を持つ大きなテーブルがあります

class BookName:
    name = models.CharField(db_index=True)
    other_names = models.ManyToManyField(OtherName)

class OtherBookName:
    name = models.CharField(db_index=True)

リストからフルネームまたは別名を持つ本を照会したい。

自然に使用Q()すると、物事がかなり遅くなります。

私の解決策は、リストに名前がある行を最初にクエリOtherBookNameし、それらの pks を返すことです (インデックスが作成されているため迅速です)。次に、2 つのモデルの間に手動で M2M テーブルを含め、テーブルで一致するインスタンスwhereも抽出する必要がある句を追加します。BookName

test_names = ["Foo", "Bar",]
other_ids = OtherBookName.objects.filter(name__in=test_names).values_list("id", flat=True)
queryset = self\
            .filter(Q(name__in=test_names)) \
            .extra(
                where=[
                    "bookname_id = app_bookname.id",
                    "booknameotherbookname_id IN (%s)" 
                        % ",".join([str(id) for id in other_ids]),
                ],
                tables=["app_bookname_otherbookname",]) \
            .distinct()

これは、必要なときに where 句がANDクエリに編集されることを除いて、ほとんど機能していますOR

4

1 に答える 1

0

Try this:

names = ["Foo", "Bar",]
other_ids = OtherBookName.objects.filter(name__in=names).values_list("id", flat=True)
where_clause = "bookname_id = app_bookname.id AND (name IN (%s)" \
                % ",".join(names) + " OR booknameotherbookname_id IN (%s))" \
                % ",".join([str(id) for id in other_ids])
queryset = self\
            .extra(
                where=[where_clause],
                tables=["app_booknames_otherbookname",]) \
            .distinct()
于 2012-11-23T20:09:43.513 に答える