在任意字段等价上预取无关模型
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(???))
^ 知道写什么也是错的 ???
.
这可以吗?你能根据任意查询预取一些完全不相关的东西吗?
另一方面,您为什么不直接将整个查询集(MyModel
和 MyOtherModel
)读入内存然后进行比较?在对 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')
我有这样的代码:
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(???))
^ 知道写什么也是错的 ???
.
这可以吗?你能根据任意查询预取一些完全不相关的东西吗?
另一方面,您为什么不直接将整个查询集(MyModel
和 MyOtherModel
)读入内存然后进行比较?在对 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')