使用Django ORM预取间接相关项
我正在尝试优化我的调节系统的查询,使用Django和DRF构建。 我目前一直在重复检索:目前,我有使用Django ORM预取间接相关项,django,query-optimization,django-orm,Django,Query Optimization,Django Orm,我正在尝试优化我的调节系统的查询,使用Django和DRF构建。 我目前一直在重复检索:目前,我有 类AdminSerializer(ModelSerializer): 重复项=SerializerMethodField() def获取副本(自身、项目): 如果允许,则: qs=[] 其他: qs=Item.objects.filter( 允许=真, related\u stuff\u language=item.related\u stuff.language ).注释( 相似性=Trigra
类AdminSerializer(ModelSerializer):
重复项=SerializerMethodField()
def获取副本(自身、项目):
如果允许,则:
qs=[]
其他:
qs=Item.objects.filter(
允许=真,
related\u stuff\u language=item.related\u stuff.language
).注释(
相似性=TrigramSimilarity('name',item.name)
).filter(相似性\uu gt=0.2).按('-similarity')[:10]排序
返回AdminMinimalSerializer(qs,many=True)
它工作正常,但对要显示的每个项目至少执行一个附加查询。此外,如果存在重复项,我将执行其他查询以填充AdminMinimalSerializer
,其中包含重复项的字段和相关对象。我可能可以通过在序列化程序中使用与预取相关的来减少开销,但这并不妨碍我对每个项进行多次查询(假设我在AdminMinimalSerializer
中只有一个相关项要预取,我仍然有~2N+1个查询:1个用于项,N个用于重复项,N个用于重复项的相关项)
我已经查看了子查询
,但是我无法检索对象,只能检索id,这在我的例子中是不够的。我尝试在预回迁
对象和注释中使用它
我还尝试了类似Item.filter(allowed=False).prefetch(prefetch(“related\u stuff\u language\u related\u stuff\u set\u items”,queryset=items.filter…,to\u attr=“duplicates”)
,但是duplicates
属性被添加到了“related\u stuff\u language\u related\u stuff\u stuff\u\u-stuff\u集”,所以我无法真正使用它
我欢迎任何意见;)
编辑:真正的代码存在。玩具示例如下:
#models.py
从django.db.models导入Model、CharField、ForeignKey、CASCADE、BooleanField
教材(模型):
title=CharField(最大长度=250)
serie=外键(serie,on\u delete=CASCADE,related\u name=“books”)
允许=布尔字段(默认值=False)
等级系列(型号):
title=CharField(最大长度=250)
language=ForeignKey(语言,on_delete=CASCADE,related_name=“series”)
课堂语言(模型):
name=CharField(最大长度=100)
#serializers.py
从django.contrib.postgres.search导入相似性
从rest_framework.serializers导入ModelSerializer,SerializerMethodField
从。模型导入书籍、语言、系列
类BookAdminSerializer(ModelSerializer):
类元:
模型=书
字段=(“id”、“标题”、“系列”、“重复项”)
serie=SeriedMinauxSerializer()
重复项=SerializerMethodField()
def获取副本(自我、书本):
“”“检索书本的副本”“”
如果允许:
qs=[]
其他:
qs=(
Book.objects.filter(
允许=真,serie\u语言=book.serie.language)
.注释(相似性=三元相似性(“书名”,书名))
.过滤器(相似性\uu gt=0.2)
.order_by(“-相似性”)[:10]
)
返回BookAdminMinimalSerializer(qs,many=True)
类BookAdminSerializer(ModelSerializer):
类元:
模型=书
字段=(“id”、“标题”、“系列”)
serie=SeriedMinauxSerializer()
类SeriedMinauxSerializer(ModelSerializer):
类元:
型号=系列
字段=(“id”、“语言”、“标题”)
language=LanguageSerializer()
类语言序列化程序(ModelSerializer):
类元:
模型=语言
字段=('id','name')
我正试图找到一种预取相关对象和副本的方法,这样我就可以摆脱BookSerializer
中的get_duplicates
方法,它会导致N+1个查询,并且在我的BookSerializer
中只有一个duplicates
字段
关于数据,以下是预期输出:
[
{
"id": 2,
"title": "test2",
"serie": {
"id": 2,
"language": {
"id": 1,
"name": "English"
},
"title": "series title"
},
"duplicates": [
{
"id": 1,
"title": "test",
"serie": {
"id": 1,
"language": {
"id": 1,
"name": "English"
},
"title": "first series title"
}
}
]
},
{
"id": 3,
"title": "random",
"serie": {
"id": 3,
"language": {
"id": 1,
"name": "English"
},
"title": "random series title"
},
"duplicates": []
}
]