[英]Get only one related object from Django queryset
I'm trying to optimize a feed-like query in Django where I get the unique items commented by users I follow. 我正在尝试在Django中优化类似feed的查询,在该查询中,我得到关注的用户评论的唯一项。
queryset_comments = Item.objects.distinct() \
.prefetch_related('comments', 'comments__user') \
.filter(comments__user__in=self.request.user.following.all()) \
.prefetch_related(
Prefetch('comments', queryset=Comment.objects.filter(
user__in=self.request.user.following.all()
).order_by('-created_on'), to_attr='activity')
) \
.all()
This gives me a related activity
object with a list of all the comments made by user I follow, with the most recent comment first. 这为我提供了一个相关的
activity
对象,其中列出了我关注的用户所发表的所有评论,其中最近的评论在前。 Now I only need the first one, so I loop other the queryset and set the values I need: 现在我只需要第一个,所以我循环其他queryset并设置所需的值:
for item in queryset_comments:
item.feed_user = item.activity[0].user
item.feed_date = item.activity[0].created_on
item.feed_activity = 'commented'
But this loop is taking more than 2 seconds with only about 500 items... I've tried to prefetch with slicing (by adding [0]
or .first()
to the Prefetch
queryset, but both methods are unsupported by Django ORM. 但是,此循环仅用了大约500个项目就花费了2秒钟以上的时间...我试图通过切片进行预取(通过在
Prefetch
集中添加[0]
或.first()
,但是Django ORM不支持这两种方法。
Any suggestion to make this a bit faster ? 有什么建议可以加快速度吗?
There was a simliar question here that made me come to the same conclusion. 这里有一个类似的问题使我得出相同的结论。
I would suggest to not use prefetch_related
, but to finish working your queryset until its ready to execute the database query. 我建议不要使用
prefetch_related
,但要完成其查询集的工作,直到准备执行数据库查询为止。 Maybe even paginated, so you only have 20 or 50 objects. 甚至可能是分页的,因此您只有20或50个对象。
Then make a list of all Item.pk
values and fetch the related "one comment per Item" yourself (using Max('created_on')
). 然后列出所有
Item.pk
值,并自己获取相关的“每个项目一个注释”(使用Max('created_on')
)。
Same thing as prefetch_related
but more control. 与
prefetch_related
但控制更多。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.