2

是否可以返回每个外键只返回一个对象的查询集?

例如,我希望从 django_comments 获取最新评论,但我只想要每个对象一个评论(最新评论),即只返回一个对象的最新评论并排除该对象的所有过去评论。我猜这类似于 django_comments.content_type 和 django_comments.object_pk 上的 sql group_by。

++添加信息++

最终目标是创建一个活动评论“线程”列表,按哪个线程具有最新评论显示/排序,就像您的标准讨论板的主题按最近活动列出一样。

我认为最好的方法是获取最新的评论,然后按内容类型和 object_pk 对它们进行排序或分组,以便每个相关内容对象只返回一个评论(最新的)。然后我可以使用该评论来获取我需要的所有信息,因此线程一词的使用很松散,因为我实际上只是在获取评论并遵循它的 pk。

模型是 django_threadedcomments,它扩展了 django_comments 并添加了一些用于树、孩子和父母的字段。

看法:

...这将返回所有评论,包括所有父级实例

comments = ThreadedComment.objects.all().exclude(is_public='0').order_by("-submit_date")

...这是理想的

comments = ThreadedComment.objects.all().exclude(is_public='0').order_by("submit_date").[plus sorting logic to exclude multiple instances of the same object_pk and content_type]

模板:

{% for comment in comments %}

TITLE: {{comment.content_object.title}}

STARTED BY : {{comment.content_object.user}}

MOST RECENT REPLY : {{comment.user}} on {{comment.submit_date}}

{% endfor %}

再次感谢!

4

3 回答 3

2

这在 SQL 中是一件相当困难的事情。您可能无法通过 ORM 做到这一点。

您不能为此使用 GROUP BY。这用于告诉 SQL 如何对项目进行分组以进行聚合,这不是您在这里所做的。“SELECT x, y FROM table GROUP BY x”是非法SQL,因为y的值没有意义。

让我们带着清晰的架构来看看这个:

CREATE TABLE objects ( id INTEGER PRIMARY KEY, name VARCHAR );
CREATE TABLE comments ( object_id INTEGER REFERENCES objects (id), text VARCHAR NOT NULL, date TIMESTAMP NOT NULL );

INSERT INTO objects (id, name) VALUES (1, 'object 1'), (2, 'object 2');
INSERT INTO comments (object_id, text, date) VALUES
   (1, 'object 1 comment 1', '2010-01-02'),
   (1, 'object 1 comment 2', '2010-01-05'),
   (2, 'object 2 comment 1', '2010-01-08'),
   (2, 'object 2 comment 2', '2010-01-09');

SELECT * FROM objects o JOIN comments c ON (o.id = c.object_id);

我见过的最优雅的方法是 Postgresql 8.4 的窗口函数。

SELECT * FROM (
    SELECT
        o.*, c.*,
        rank() OVER (PARTITION BY object_id ORDER BY date DESC) AS r
    FROM objects o JOIN comments c ON (o.id = c.object_id)
) AS s
WHERE r = 1;

这将按日期为每个对象选择第一个评论,最新的在前。如果您看不到这是在做什么,请自行执行内部 SELECT 并观察它如何生成 rank(),这使其非常简单。

我知道使用 Postgresql 执行此操作的其他方法,但我不知道如何在其他数据库中执行此操作。

尝试动态计算它可能会让您非常头疼——而且要使这些复杂的查询表现良好也需要做更多的工作。您最好以简单的方式执行此操作:last_comment_id为每个对象存储一个字段,并在添加或删除评论时更新它,这样您就可以加入和排序。您可能可以使用 SQL 触发器来自动处理此更新。

于 2010-06-20T23:22:14.633 回答
0

感谢格伦和 vdboor。同意,所提出的想法创造了许多 sql 复杂性的方式,并将严重影响性能。

last_comment_id 建议非常好,但我相信对于我的特殊情况,最好的办法是创建一个单独的“线程”模型,该模型存储评论的原始对象的 content_type 和 object_pk 以及对象的 id 和时间戳最后的评论,以及其他几件事。这将允许简单的内容对象查找和按时间顺序过滤的查询集,并使幕后发生的事情更接近于前端演示,这对于后代来说可能是一个好主意。:)

干杯,

关注

于 2010-06-21T16:41:52.467 回答
-1

考虑将最后一个帖子作为外键存储在某处(例如,在父对象表中)。每次发布或删除消息时,更新此密钥。

是的,这是重复的,但值得考虑。必须为每个请求(尤其是索引页面)运行复杂的查询可能会降低您的应用程序性能。这是在不损失性能的情况下获得预期效果的实用方法。

于 2010-06-21T07:33:46.817 回答