在任意字段等价上预取无关模型

Prefetching unrelated model on arbitrary field equivalence

我有这样的代码:

for m in MyModel.objects.filter(...):
    mo = MyOtherModel.objects.get(myOtherField=m.myField)
    print("{:s}{:s}".format(m, mo))

这是低效的,因为查找 mo 需要对数据库进行新查询。

为了避免这种情况,我正在考虑使用 prefetch_related(Prefetch()).annotate()

第一个问题是 Prefetch() 需要两个模型之间的外键关系(它们有 none)。

同样的事情.annotate:

MyModel.objects.filter(...).annotate(moWithSameField=F('myField') == F(???))

^ 知道写什么也是错的 ???.

这可以吗?你能根据任意查询预取一些完全不相关的东西吗?

另一方面,您为什么不直接将整个查询集(MyModelMyOtherModel)读入内存然后进行比较?在对 db

的查询数量方面会很有效
m_rows = MyModel.objects.filter(...)
m = m_rows.order_by('myField').values_list('myField')
m_set = set([x for x in m])
mo_rows = MyOtherModel.objects.all()
mo = mo_rows.values_list('myOtherField')
mo_set = set([x for x in mo])
common = list(m_set.intersection(mo_set))
mo_result = MyOtherModel.objects.filter(myOtherField__in=common).order_by('myOtherField')
for i in range(len(mo_result)):
    print("{:s}{:s}".format(m_rows[i], mo_rows[i]))    

我认为这太复杂了,应该有更好的方法来做到这一点。 但这可以节省您对 db 的 n 个查询。

有几点:
1- 如果这些查询将 运行 在具有大数据的操作系统中由用户请求,您需要重新设计您的 ER 模型或考虑其他解决方案。
2-如果你没有内存不足的问题,你可以用两个查询将模型的整个对象加载到内存中。

MyOtherModelAll=MyOtherModel.objects.all()
for m in MyModel.objects.filter(...):
   for mo in MyOtherModelAll:
   if(mo.myOtherField=m.myField)
        print("{:s}{:s}".format(m, mo))  

3。 Annotate 方法告诉 Django 为每个对象添加一个额外的属性 returned.The 下面的示例对你有用:

Book.objects.annotate(search=searchVector  ('title','abstract'),).filter(search='django')