TYPO3 Extbase Repository Query: Как найти записи в отношении M:N, где задано несколько значений для N?

У нас есть простая модель Company. В каждой компании может быть один или несколько отделов Dept. Каждый отдел относится к определенному типу Type.

Теперь нам нужен запрос, в котором возвращаются все компании, у которых есть отдел типа X и хотя бы один типа Y (т.е. каждая возвращаемая компания имеет два или более отдела, хотя бы один X и один Y ).

Как это можно сделать с помощью запроса?

Этот запрос не дает результатов, если getTypes возвращает более одного типа.

if (count($types = $demand->getTypes()) > 0) {
    foreach ($types as $type)
        $constraints[] = $query->contains('dept.type', $type);
}

$result = $query->matching($query->logicalAnd($query->logicalAnd($constraints)))->execute();

Этот запрос возвращает результаты для типа X или Y.

if (count($types = $demand->getTypes()) > 0) {
    $constraints[] = $query->in('dept.type', $types);
}

Таблицы выглядят так (упрощенно):

CREATE TABLE IF NOT EXISTS `company` (
  `uid` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(128) NOT NULL,
  PRIMARY KEY (`uid`)
);

CREATE TABLE IF NOT EXISTS `dept` (
  `uid` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(128) NOT NULL,
  `company` int(10) unsigned NOT NULL,
  `type` int(10) unsigned NOT NULL,
  PRIMARY KEY (`uid`)
);

CREATE TABLE IF NOT EXISTS `type` (
  `uid` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(128) NOT NULL,
  PRIMARY KEY (`uid`)
);

person rantanplan    schedule 02.04.2013    source источник
comment
Я, конечно, мог бы сделать один запрос для каждого типа, а затем взять пересекающийся набор... но это не очень элегантно!   -  person rantanplan    schedule 03.04.2013
comment
Тип поля в таблице dept — целое число без знака (10). Как может быть больше одного отношения? Я знаю назначение, разделенное запятыми, но для этого требуется строка. Я также знаю 1: n, но для этого требуется дополнительное поле в типе таблицы, и это не имеет смысла, а для отношения M: N требуется дополнительная таблица. Проверьте настройки TCA и бэкенда, все ли там работает нормально.   -  person Merec    schedule 03.04.2013
comment
У каждого отдела есть только один тип, поэтому вполне достаточно одного поля int. Но в компании есть один или несколько отделов. В этом смысле таблица отделов — это таблица mn--- Все отношения в этой модели в порядке. Это просто поиск решения запроса.   -  person rantanplan    schedule 03.04.2013


Ответы (2)


if (count($types = $demand->getTypes()) > 0) {
    foreach ($types as $type)
        $constraints[] = $query->contains('dept.type', $type);
}

Вы не показываете дальнейшую обработку.

Если вам нужна операция AND, используйте это:

$result = $query->matching($query->logicalAnd($query->logicalAnd($constraints)))->execute();

Если вам нужна операция ИЛИ, используйте это:

$result = $query->matching($query->logicalAnd($query->logicalOr($constraints)))->execute();

ХТН

person fazzyx    schedule 24.04.2013
comment
Первый блок кода — это просто ваша цитата. Но вы не показываете дальнейшую обработку. Если вам нужен результат X AND Y, попробуйте ограничение $query-›contains и вызов метода сопоставления с операцией AND, как я написал. - person fazzyx; 26.04.2013
comment
Ок, извините, я виноват, я не правильно прочитал. Как насчет двухэтапного запроса? Вы уже пробовали это? Во-первых: получить все отделы по типу. Далее : Получить все компании по отделам - person fazzyx; 29.04.2013

Я обнаружил, что $query->contains() правильно работает только с простыми таблицами _mm.

Итак, вот что я сделал: я просто добавил представление в БД, в котором есть необходимые поля для таблицы _mm:

CREATE VIEW `company_type_mm` AS
SELECT 
    `company` AS `uid_local`, 
    `type` AS `uid_foreign`,
    0 AS `sorting`,
    0 AS `sorting_foreign` 
FROM `dept`;

Затем я добавил новое поле dept в TCA таблицы company:

'type' => array(
    ...
    'config' => array(
        'foreign_table' => 'type',
        'MM' => 'company_type_mm',
        ...
    )
)

И теперь я получаю правильные результаты для компаний, в которых есть отделы типа A и типа B, например:

if (count($types = $demand->getTypes()) > 0) {
    foreach ($types as $type)
        $constraints[] = $query->contains('type', $type);
}
person rantanplan    schedule 30.04.2013