Как сопоставить записи, связанные с определенным набором других записей?

Я пытаюсь добавить в свой проект два разных варианта поиска. Есть модель "Пользователь" и модель "Тег". У пользователя много тегов. Теперь я хочу иметь возможность искать пользователей с определенными тегами. Либо я хочу показать всех пользователей, у которых есть любой из указанных тегов. У меня это работает следующим образом:

$query = $this->Users->find();
$query->matching('Tags', function ($q) {
    return $q->where(['Tags.name' => 'Tag1'])
             ->orWhere(['Tags.name' => 'Tag2']);
});

Но теперь я хочу найти всех пользователей, у которых есть оба тега одновременно. Пробовал ->andWhere вместо ->orWhere, но результат всегда пустой.

Как я могу найти пользователей, которые содержат несколько тегов?

Спасибо


person conehead    schedule 19.06.2015    source источник


Ответы (1)


Есть несколько способов добиться этого, один из них состоит в том, чтобы сгруппировать результаты и использовать HAVING для сравнения количества отдельных тегов.

$query = $this->Users
    ->find()
    ->matching('Tags', function ($query) {
        return $query->where(['Tags.name IN' => ['Tag1', 'Tag2']]);
    })
    ->group('Users.id')
    ->having([
        $this->Users->query()->newExpr('COUNT(DISTINCT Tags.name) = 2')
    ]);

При этом будут выбраны только те пользователи, у которых есть два разных тега, которые могут быть только Tag1 и Tag2, поскольку объединяются только они. В случае, если столбец name уникален, вместо этого вы можете рассчитывать на первичный ключ.

IN кстати. по существу то же самое, что и ваши OR условия (система базы данных соответственно расширяет IN до OR условий).

person f.poller    schedule 19.06.2015
comment
Извините, мне потребовалось время. Но работает идеально! Большое спасибо! - person conehead; 30.06.2015