问一个蒟蒻的 DjangoORM 问题

2015-06-21 14:02:41 +08:00
 dingyaguang117

要查询每个(其实是一个列表中的)用户的最后一条评论

Model定义伪代码

class Comment():
   user_id
   text
   create_time

查询user_id in [1,2,3,4,5]中的的最后一条评论,用Django ORM怎么写? 如果不行的话,SQL怎么写呢

3815 次点击
所在节点    Django
12 条回复
yzongyue
2015-06-21 15:41:22 +08:00
我觉得吧,,,
Model定义伪代码
class Comment():
user
text
create_time
然后,
clist = []
for u_id in u_ids:
c = Comment.objects.filter(user__id__exact=u_id).order_by('create_time')[0]
clist += c

命名不规范,大体这意思
dingyaguang117
2015-06-21 16:27:03 +08:00
@yzongyue 现在要一条sql出结果。。。
tini20
2015-06-21 16:51:23 +08:00
要想速度好,这个最好用一个专门的表存储
dalang
2015-06-21 19:56:06 +08:00
@yzongyue 感觉可以写成
Comment.objects.filter(user__id__in=u_ids).latest('create_time')
dingyaguang117
2015-06-21 19:59:43 +08:00
@dalang 这样是只返回所有里面最新的一条吧?
yzongyue
2015-06-21 22:10:22 +08:00
@dalang 还有latest啊,忘了,,题主要求取出每个人的最新评论
dalang
2015-06-21 22:17:03 +08:00
@dingyaguang117 确实误解题意了

没想到一句 sql 的方法。能想到两条 sql 的,先求出每个 user 对应最新评论的日期:condition_list = Comment.objects.values('user').annotate(create_time=Max('create_time'))

会得到一个类似[{'create_time': datetime.datetime(2015, 5, 21, 11, 15, 57, tzinfo=<UTC>), 'user': 1L}...] 的 list

然后用一个 sql 把对应的评论找出来
query = reduce(lambda q,v: q|(Q(user=v['user')&Q(create_time=v['create_time'])), condition_list, Q())
Comment.objects.filter(query)
dingyaguang117
2015-06-21 22:34:56 +08:00
@dalang 我现在就是这样,第二个用in就可以了
dingyaguang117
2015-06-21 22:36:24 +08:00
@dalang django好像对 group by 的控制比较让人费解。。。似乎子查询也必须用raw sql
aggron
2015-06-22 08:14:15 +08:00
希望你用的是postgre,那可以用这样的raw sql:
select * from comment c where id in ( select id from comment c1 where c2.userId in (1,2,3,4) and c1.useId=c.userId limit 1)
如果myaql,参考 /t/198719
aggron
2015-06-22 08:19:15 +08:00
typo,应该是c1.userId in
shengrang
2015-06-22 08:30:16 +08:00
@dalang 正解吧

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/200172

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX