gpt4 book ai didi

django - O(1) Django ORM策略查询相关对象的相关对象

转载 作者:行者123 更新时间:2023-12-01 19:11:04 25 4
gpt4 key购买 nike

Foo和Bar之间的关系是通过Baz实现的,如下:

class Foo(Model):
# stuff

class Bar(Model)
# stuff

class Baz(Model):
foos = ManyToManyField("Foo")
bar = ForeignKey("Bar")

我基本上需要生成以下字典,表示通过 Baz 与每个 Foo 相关的 Bars (在字典理解伪代码中) ):

{ foo.id: [通过任何 baz 与 foo 相关的唯一栏列表],用于所有 foo 中的 foo}

我目前可以使用 O(N) 查询(每个 Foo 1 个查询)生成数据结构,但是对于大量数据,这是一个瓶颈,我需要将其优化到 O(1) (本身不是单个查询) ,但无论任何模型的数据大小如何,查询的数量都是固定的),同时还最大限度地减少了 python 中数据的迭代。

最佳答案

如果您可以使用 SQL,则可以使用单个查询(应用程序名称应作为所有表名称的前缀):

select distinct foo.id, bar.id
from baz_foos
join baz on baz_foos.baz_id = baz.id
join foo on baz_foos.foo_id = foo.id
join bar on baz.bar_id = bar.id

baz_foos 是 Django 创建的多对多表。

@Alasdair 的解决方案可能/可能更具可读性(尽管如果您这样做是出于性能原因,那可能不是最重要的)。他的解决方案恰好使用了两个查询(这几乎没有区别)。我看到的唯一问题是如果您有大量 Baz 对象,因为生成的 sql 如下所示:

SELECT "foobar_baz"."id", "foobar_baz"."bar_id", "foobar_bar"."id" 
FROM "foobar_baz"
INNER JOIN "foobar_bar" ON ("foobar_baz"."bar_id" = "foobar_bar"."id")

SELECT
("foobar_baz_foos"."baz_id") AS "_prefetch_related_val",
"foobar_foo"."id"
FROM "foobar_foo"
INNER JOIN "foobar_baz_foos" ON ("foobar_foo"."id" = "foobar_baz_foos"."foo_id")
WHERE "foobar_baz_foos"."baz_id" IN (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94,
95, 96, 97, 98, 99, 100, 101)

如果你只有几个 Bar 和几百个 Foo,我会这样做:

from django.db import connection
from collections import defaultdict

# foos = {f.id: f for f in Foo.objects.all()}
bars = {b.id: b for b in Bar.objects.all()}

c = connection.cursor()
c.execute(sql) # from above
d = defaultdict(set)
for f_id, b_id in c.fetchall():
d[f_id].add(bars[b_id])

关于django - O(1) Django ORM策略查询相关对象的相关对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27851415/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com