Всем привет) Я использую Laravel, MariaDB.
Например, у нас есть такая таблица, скажем категории.
Модель «Категории» использует признак Kalnoy\Nestedset\NodeTrait. В приведенном ниже коде построитель запросов уже содержит базовые фильтры (например, по имени).
if (!empty($filters['recursiveSearch']) && CommonService::parseBoolean($filters['recursiveSearch']) === true) {
/** @var QueryBuilder $query */
}
При передаче параметра recursiveSearch необходимо вывести не только значения, соответствующие фильтру, но и всех их родителей.
Например: по имени фильтра=adjust мы получаем строку Корректировка. с recursiveSearch вам также необходимо получить Windows и Glass unit.
Запрос также может иметь родительский идентификатор фильтра. Если parentId=null&name=adjust&recursiveSearch=true
, то он должен вернуть Windows
Пожалуйста помоги :)
Сначала я думал сделать просто with('ancestors')
, но результат попадает в отношения и должен быть в основном запросе.
Потом я сделал дополнительный запрос, получил результат первой выборки, получил pluck('ancestors')
и уже подставил их идентификаторы в результирующий запрос. Это сработало, но если в первоначальной выборке будет, например, 1000 записей и у каждой будет по 3 родителя, то в итоге будет где-то по 3000 ID.
По идее, не принимая во внимание Laravel, вы можете сделать это без рекурсии, поскольку у вас есть полный путь для каждой строки.
select p.*
from categories c
inner join categories p on
find_in_set(cast(p.id as char),replace(c.path,'.',','))>0
where c.id=1377
Проще сделать это с помощью 2 запросов
select path from categories where id=1377
Вывод: «1373.1374.1377».
2. Опросить всех родителей с параметром «1373,1374,1377».
select *
from categories
where find_in_set(cast(id as char),'1373,1374,1377')>0
Запрос идентификатора и всех детей
select *
from categories c
where find_in_set(cast(1374 as char),replace(c.path,'.',','))>0
$query->join('categories as p', function ($join) {
$join->on(DB::raw("FIND_IN_SET(CAST(p.id AS CHAR) COLLATE utf8mb4_unicode_ci, REPLACE(categories.path COLLATE utf8mb4_unicode_ci, '.', ','))"), '>', DB::raw('0'));
})
->addSelect('p.*')
->distinct();
Это сработало в Ларавеле.
Вы можете использовать рекурсивный запрос CTE.