CakePHP find() group and order by date 复杂条件
CakePHP find() group and order by date complex conditions
我正在尝试获取与相应用户的消息,以便按时间顺序显示配置文件的聊天列表以及他们的最后一条消息。
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",
- 按时间顺序
问题:
- 查询不会从 $recepient_id/$sender_id 组合中检索最新消息。
所以我没有包含最后一条消息的用户列表,而是包含一条消息的用户列表。我的查询有什么问题?感谢您的帮助!
方法 2 结果
我在数据库中创建了 "chat_id" 字段,该字段基本上按字母顺序 recepient_id+sender_id 排序(因为如果用户 1 向用户 2 发送消息,则用户 1 是发件人,稍后当用户 2 响应时,他成为发件人,因此排序将确保两个用户始终具有相同的 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)
)
)
));
而且它不起作用!我现在收到同一个对话的多条消息。
如果我从查询中删除 Message 字段和 Recipient 字段,我会得到正确数量的 "chats"。
'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.I 正在获取聊天列表,2.I 想从每个聊天中找到最后一条消息。
根据 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']
不一样!
终于!工作解决方案:
$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) 两个更聪明的查询 更简单的方法,select 仅 "ids" 条消息并创建另一个查询,该查询将包含蛋糕的构建行为。这也可能更好,因为将应用行为。
您将得到数组树,为下一次查询使用以下内容挖掘实际 ID:
$chats = Set::extract("/Message/id",$chats);
c) 将解决方案转化为 CakePHP 查询生成器...:) 准备好迎接挑战了吗?
我正在尝试获取与相应用户的消息,以便按时间顺序显示配置文件的聊天列表以及他们的最后一条消息。
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",
- 按时间顺序
问题:
- 查询不会从 $recepient_id/$sender_id 组合中检索最新消息。
所以我没有包含最后一条消息的用户列表,而是包含一条消息的用户列表。我的查询有什么问题?感谢您的帮助!
方法 2 结果
我在数据库中创建了 "chat_id" 字段,该字段基本上按字母顺序 recepient_id+sender_id 排序(因为如果用户 1 向用户 2 发送消息,则用户 1 是发件人,稍后当用户 2 响应时,他成为发件人,因此排序将确保两个用户始终具有相同的 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)
)
)
));
而且它不起作用!我现在收到同一个对话的多条消息。
如果我从查询中删除 Message 字段和 Recipient 字段,我会得到正确数量的 "chats"。
'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.I 正在获取聊天列表,2.I 想从每个聊天中找到最后一条消息。 根据 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']
不一样!
终于!工作解决方案:
$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) 两个更聪明的查询 更简单的方法,select 仅 "ids" 条消息并创建另一个查询,该查询将包含蛋糕的构建行为。这也可能更好,因为将应用行为。
您将得到数组树,为下一次查询使用以下内容挖掘实际 ID:
$chats = Set::extract("/Message/id",$chats);
c) 将解决方案转化为 CakePHP 查询生成器...:) 准备好迎接挑战了吗?