Запрос репозитория TYPO3 9.5 для выборки элементов с несколькими sys_categories - PullRequest
0 голосов
/ 19 июня 2019

Я пытаюсь выяснить, как написать следующий запрос для извлечения некоторых элементов, которые имеют несколько категорий.

$query->matching(
    $query->logicalAnd(
        [
            // the following 4 lines are the problem lines
            $query->logicalAnd(
                $query->in('categories.uid', $categories),
                $query->in('categories.uid', $countryCategories)
            ),
            // $query->in('categories.uid', $categories),
            // $query->in('categories.uid', $countryCategories),

            $query->logicalOr(
                [
                    $query->equals('is_pinned', 0),
                    $query->lessThan('pinned_until', time())
                ]
            ),
        ]
    )
);

Идея состоит в том, чтобы выбрать элементы, где categories.uid соответствует хотя бы одному uid в $categories и хотя бы одному в $countryCategories. И $categories, и $countryCategories - это массивы, заполненные категориями.

Запрос работал нормально, пока не была вставлена ​​вторая строка $query->in('categories.uid' [...]. Как только вторая строка вставлена, результат запроса будет пустым. Вероятно, это ошибка в запросе, но ни я, ни мой коллега не смогли найти рабочее решение.

При поиске я обнаружил sql UNION, с которым я никогда раньше не работал, но я догадался, что это был бы путь, если бы мне пришлось написать утверждение вместо построения запроса.

Что я хотел бы знать, так это то, можно ли получить элементы с помощью "построителя запросов" или действительно необходимо написать заявление? Если есть решение с помощью построителя запросов, не могли бы вы указать мне? Если нет, то как мне построить запрос с помощью UNION для выборки элементов по мере необходимости?

Если что-то неясно, пожалуйста, не стесняйтесь спрашивать, я постараюсь уточнить дальше. Благодаря.


EDIT

Мы также отладили запрос, и я выполнил его напрямую в phpmyadmin. Он работал без "AND (sys_category.uid IN ( 41, 2 ))", но с ним результат пуст. Следующим был отлаженный запрос:

SELECT `tx_gijakobnews_domain_model_news`.* 
 FROM `tx_gijakobnews_domain_model_news` `tx_gijakobnews_domain_model_news` 
    LEFT JOIN `sys_category_record_mm` `sys_category_record_mm` ON ( `tx_gijakobnews_domain_model_news`.`uid` = `sys_category_record_mm`.`uid_foreign`)  AND (( `sys_category_record_mm`.`tablenames` = 'tx_gijakobnews_domain_model_news') AND ( `sys_category_record_mm`.`fieldname` = 'categories'))  
    LEFT JOIN `sys_category` `sys_category` ON `sys_category_record_mm`.`uid_local` = `sys_category`.`uid` 

    WHERE ((
            (`sys_category`.`uid` IN ( 15, 17, 10, 11, 12, 16, 13, 14 ))
            ////// this following line is where the problem begins
            AND (`sys_category`.`uid` IN ( 41, 2 ))
    )
/////////// the following lines are additional restrictions
/////////// which have no influence on the problem
        AND ((`tx_gijakobnews_domain_model_news`.`is_pinned` = 0) OR ( `tx_gijakobnews_domain_model_news`.`pinned_until` < 1560867383))
    )
 AND ( `tx_gijakobnews_domain_model_news`.`sys_language_uid` IN ( 0, -1) )  
 AND ( `tx_gijakobnews_domain_model_news`.`pid` = 31)  
 AND ( ( `tx_gijakobnews_domain_model_news`.`deleted` = 0)  
 AND ( `tx_gijakobnews_domain_model_news`.`t3ver_state` <= 0)  
 AND ( `tx_gijakobnews_domain_model_news`.`pid` <> -1)  
 AND ( `tx_gijakobnews_domain_model_news`.`hidden` = 0)  
 AND ( `tx_gijakobnews_domain_model_news`.`starttime` <= 1560867360)  
 AND ( ( `tx_gijakobnews_domain_model_news`.`endtime` = 0)  
 OR ( `tx_gijakobnews_domain_model_news`.`endtime` > 1560867360) ) )  
 AND ( ( ( `sys_category`.`deleted` = 0)  
 AND ( `sys_category`.`t3ver_state` <= 0)  
 AND ( `sys_category`.`pid` <> -1)  
 AND ( `sys_category`.`hidden` = 0)  
 AND ( `sys_category`.`starttime` <= 1560867360)  
 AND ( ( `sys_category`.`endtime` = 0)  
 OR ( `sys_category`.`endtime` > 1560867360) ) )  
 OR ( `sys_category`.`uid` 
 IS NULL) )  
 ORDER BY `tx_gijakobnews_domain_model_news`.`publish_date` DESC

Если отсутствует скобка, я, вероятно, случайно удалил ее при форматировании ...

Ответы [ 2 ]

0 голосов
/ 19 июня 2019

Я считаю, что проблема в том, что предложение where применяется на основе "на строку".

Значение Если у вас есть запрос, подобный следующему (на основе вашего запроса):

SELECT *
FROM news
LEFT JOIN sys_category_record_mm mm
  ON (news.uid = mm.uid_foreign) /* AND (...) */
LEFT JOIN sys_category
  ON mm.uid_local = sys_category.uid
WHERE
  sys_category.uid IN (1,2,3)
  AND sys_category.uid IN (4,5,6)

Возможно, у вас есть одна новостная статья, которая относится к категории 1 и категории 4. Но набор результатов будет состоять из двух отдельных строк:

news.uid | sys_category.uid
1        | 1
1        | 4

и предложение WHERE отфильтровывает их обоих, потому что sys_category.uid не и в (1, 2, 3) и в (4, 5, 6) для каждого ряда индивидуально.

Способ сделать это на уровне SQL, вероятно, состоит в том, чтобы сделать два соединения с sys_category. Но я не верю, что это возможно с помощью (довольно простого) компоновщика запросов extbase.

Edit:

В качестве решения вы можете использовать метод $query->statement(), который позволяет использовать пользовательские SQL-запросы.

$result = $query->statement('SELECT news.* FROM news');

https://docs.typo3.org/m/typo3/book-extbasefluid/master/en-us/6-Persistence/3-implement-individual-database-queries.html

0 голосов
/ 19 июня 2019

Вы можете создать свой собственный запрос с помощью QueryBuilder.Примерно так:

use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Utility\DebuggerUtility;


$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
    ->getQueryBuilderForTable('table_to_select_from');

$result = $queryBuilder->select('*')
        ->from('table_to_select_from')
        ->where($queryBuilder->expr()->in('field', ['1','2','3'])
        ->execute()
        ->fetchAll();

DebuggerUtility::var_dump($result);

Вот документация:
https://docs.typo3.org/m/typo3/reference-coreapi/master/en-us/ApiOverview/Database/QueryBuilder/Index.html

...