【问题标题】:CakePHP find() group and order by date complex conditionsCakePHP find() 按日期复杂条件分组和排序
【发布时间】:2015-09-17 19:12:28
【问题描述】:

我正在尝试获取与其对应用户的消息,以便按时间顺序显示个人资料的聊天列表以及他们的最后一条消息。

array(
    0 => array(
        'Recepient' => array(
            'id' => ...
            'name' => ...
            ...
        ),
        'Message' => array(
            'content' => ...
            'created' => ...
            ...
        )
    ),
    1 => ...
)

为了检索结果,我编写了这个 find() 方法:

$msgs = $this->Message->find('all', array(
    'group' => array('Recepient.id'),
    'order'=>'Message.created DESC',
    'conditions'=>
        array(
            'OR'=> array(
                array('recepient_id'=>$pid),
                array('sender_id' => $pid)
            )
    )
));

我有什么:

  • 带有相应“收件人”的消息,
  • 按时间顺序

问题:

  • 查询不检索来自 $recepient_id/$sender_id 组合的最新消息。

因此,我有一个带有消息的用户列表,而不是带有最后一条消息的用户列表。我的查询有什么问题?感谢您的帮助!

方法 2 结果

我在数据库中创建了“chat_id”字段,它基本上是按字母顺序排序的recepient_id+sender_id(因为如果user1向user2发送消息user1是发送者,稍后当user2响应时,他成为发送者,因此排序将确保两个用户将始终具有相同的 chat_id)。

比我在查询中添加 DISTINCT:

$this->Message->recursive = 0; $msgs = $this->Message->find('all', array( 'fields' => array('DISTINCT Message.chat_id','Message.*','Recepient.*'), 'order'=>'Message.created DESC', 'conditions'=> array( 'OR'=> array( array('recepient_id'=>$pid), array('sender_id' => $pid) ) ) ));

它不起作用!我现在收到同一个对话的多条消息。

如果我从查询中删除消息字段和收件人字段,我会得到正确数量的“聊天”。 'fields' => array('DISTINCT Message.chat_id'), 但这不是解决方案。

CakePHP 2.7.0 版 MySQL数据库

方法 3 结果

$msgs = $this->Message->find('all', array( 'order'=>'Message.created DESC', 'fields' => 'recepient_id, content, max(Message.created) as max_created', 'group'=>'recepient_id', // 'contain' => array('Recepient'), 'conditions'=>array( 'chat_id' => $chats ) ));

我放弃了解决这个问题的单一查找方法,所以现在 1.我正在获取聊天列表,2.我想从每个聊天中找到最后一条消息。 根据http://www.xaprb.com/blog/2006/12/07/how-to-select-the-firstleastmax-row-per-group-in-sql/,我的查找查询应该可以工作。会发生什么

(int) 0 => array(
        'Message' => array(
            'recepient_id' => '55e6d764-1444-4aad-a909-9042f07f76da',
            'content' => '1st msg',
            'created' => '2015-09-20 18:24:17',
            'created_nice' => '2  hours ago'
        ),
        (int) 0 => array(
            'max_created' => '2015-09-20 18:24:28'
        )
    ),

max(Message.created) 字段确实显示了来自对话的最新消息,但 0=>Message 数组用于不同的消息!如您所见,$results[0]['Message']['created'] 时间和$results[0][0]['max_created'] 是不同的!

【问题讨论】:

  • Message 有很多Recipient 吗?您是否检查了 Cake 生成的 SQL 查询以找到这个结果?我怀疑查询不是您所期望的!
  • 你使用的是什么版本的 CakePHP?
  • 听起来像distinct 是一个你应该看看的术语......在book 中有distinct 的例子......
  • 你知道如何为此编写 SQL 语句吗?如果有,请分享。如果不是,那么当您的问题是从$recepient_id/$sender_id 组合中检索最新消息 时,您至少不想GROUP BY Recipient.id。您还需要说明您正在使用的数据库。
  • 为我们提供更多关于 list of users with the last message, I have a list of users with a message 的含义的背景信息。他们对我来说听起来没有什么不同

标签: cakephp find cakephp-2.7 cakephp-2.x


【解决方案1】:

终于!工作解决方案:

$db = $this->Message->getDataSource();
$chats = $db->fetchAll(
    'select id from (select * from messages order by created desc) Message
    where recepient_id = "'.$pid.'" or sender_id = "'.$pid.'"
    group by `chat_id`'
);

以上代码将按照要求检索所有消息。你可以

a) SINGLE QUERY 添加 mysql JOIN 以包含关联模型(我们保持代码单查询整洁)

b) 两个更智能的查询更简单的方法,只选择消息的“ID”并创建另一个查询,该查询将具有蛋糕的可包含行为。这也可能会更好,因为会应用行为。

因此,您将获得数组树,以挖掘出实际 id 以供下一个查询使用:

$chats = Set::extract("/Message/id",$chats);

c) 将解决方案翻译成 CakePHP 查询生成器... :) 准备好迎接挑战了吗?

【讨论】:

    猜你喜欢
    • 2015-05-11
    • 1970-01-01
    • 1970-01-01
    • 2011-02-19
    • 2023-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-07
    相关资源
    最近更新 更多