CakePHP find() группа и порядок по дате сложные условия
Я пытаюсь получать сообщения с соответствующими пользователями, чтобы отобразить список чатов с последним сообщением в хронологическом порядке.
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(
Сообщение.
созданный)
действительно показывает последнее сообщение из разговора, но массив сообщений 0=> предназначен для другого сообщения! Как вы видете $results[0]['Message']['created']
время и $results[0][0]['max_created']
разные!
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, чтобы включить ассоциированную модель (мы сохраняем код простого запроса чистым)
б) ДВА ЗАПРОСА, НО УМНОГО более простой метод, чтобы выбрать только "идентификаторы" сообщений и создать еще один запрос, который будет иметь встроенное поведение торта. Это может быть лучше, потому что Поведение будет применяться.
В результате у вас будет дерево массивов, чтобы найти действительные идентификаторы для следующего запроса:
$chats = Set::extract("/Message/id",$chats);
в) перевести решение в построитель запросов CakePHP...:) на вызов?