Я хочу иметь в своей модели вместо полного набора записей моделей, содержащихся в другой, только их количество. Я мог бы сделать это, добавив поле «размер» в набор результатов, но я хотел бы сделать это в запросе, так как я хочу динамически разбивать на страницы и упорядочивать результаты. Я использую этот код, но по какой-то причине, если первый счетчик отличен от нуля, оба поля счетчика имеют одинаковое значение, которое является значением второго поля счетчика.
$query = $this->Users->find('all')
->contain(['Likes','Favs']);
$query
->select(['like_count' => $query->func()->count('Likes.id')])
->leftJoinWith('Likes')
->group(['Users.id'])
->autoFields(true);
$query
->select(['fav_count' => $query->func()->count('Favs.id')])
->leftJoinWith('Favs')
->group(['Users.id'])
->autoFields(true);
$this->paginate['sortWhitelist'] = [
'name',
'email',
'last_login',
'fav_count',
'like_count',
];
Я хотел бы знать, почему это происходит, и есть ли какой-либо другой способ сделать то, что я пытаюсь сделать, а именно иметь («имя», адрес электронной почты, «last_login», количество записей в «Нравится» с идентификатором пользователя, количество записей в Favs с идентификатором пользователя). Я попытался использовать функцию join() для левого соединения, но мне не удалось получить желаемый результат.
Если у вас есть несколько объединений, вам нужно считать с помощью DISTINCT
, например:
COUNT(DISTINCT Likes.id)
Это связано с тем, что ваш результат будет содержать Likes * Favs
количество строк, так как для каждого объединенного лайка будут объединены все избранные, то есть для 2
лайков и 10
избранного вы получите всего 20
строк. Обычный COUNT()
будет включать каждую из этих строк.
Также обратите внимание, что вам не нужно повторять всю эту группировку и т. д., И вы можете использовать вызываемый объект для select()
, чтобы не разбивать конструктор.
$query = $this->Users
->find('all')
->select(function (\Cake\ORM\Query $query) {
return [
'like_count' => $query->func()->count(
$query->func()->distinct(['Likes.id' => 'identifier'])
),
'fav_count' => $query->func()->count(
$query->func()->distinct(['Favs.id' => 'identifier'])
),
];
})
->autoFields(true)
->contain(['Likes', 'Favs'])
->leftJoinWith('Likes')
->leftJoinWith('Favs')
->group(['Users.id']);
Использование построителя функций для генерации DISTINCT
является обходным путем, так как пока нет API, который позволил бы специально сгенерировать ключевое слово. Результатом будет что-то вроде DISTINCT(Likes.id)
, но он будет работать нормально, круглые скобки будут интерпретироваться как часть выражения после ключевого слова, а не как часть вызова функции.
Большое спасибо! Добавление отдельного предложения было ключом к моей проблеме