2010-10-19 4 views
1

Я определил эти отношения в моей модели:Почему CakePHP дублирует мои запросы? (Это не то же самое «слишком много запросов» проблема, которая обычно просят)

Lead hasMany Работа
Работа HABTM Сотрудник
Работа HABTM Грузовик

Я пытаюсь сделать find('all') из моей тележки модели и ограничить результаты:

  1. всех грузовые автомобили,
  2. всех работ, связанные с этими грузовиками т шляпа имеет определенную дату пикапа,
  3. сотрудников, назначенных на эти задания,
  4. и сведения, связанные с работой.

Вот моя операция поиска:

// app/models/truck.php 
$this->find('all', array(
    'contain' => array(
     'Job' => array(
      'Employee', 
      'Lead', 
      'conditions' => array(
       'Job.pickup_date' => $date 
      ) 
     ) 
    ) 
)); 

По какой-то причине, Cake делает запрос, чтобы найти сотрудников ДВАЖДЫ. Это приводит к тому, что все сотрудники представляются два раза для каждой работы. Вот SQL дамп:

  1. SELECT `Truck`.`id`, `Truck`.`truck_number` 
    FROM `trucks` AS `Truck` 
    WHERE 1 = 1;
  2. SELECT `Job`.`id`, `Job`.`lead_id`, `Job`.`city`, 
         `JobsTruck`.`id`, `JobsTruck`.`job_id`, `JobsTruck`.`truck_id` 
    FROM `jobs` AS `Job` 
    JOIN `jobs_trucks` AS `JobsTruck` ON (`JobsTruck`.`truck_id` IN (2, 3) 
    AND `JobsTruck`.`job_id` = `Job`.`id`) 
    WHERE `Job`.`pickup_date` = '2010-10-06'
  3. SELECT `Lead`.`id`, `Lead`.`name`, `Lead`.`created` FROM `leads` AS `Lead` 
    WHERE `Lead`.`id` = 4
  4. SELECT `Employee`.`id`, `Employee`.`name`, `Employee`.`created`, 
         `EmployeesJob`.`id`, `EmployeesJob`.`employee_id`, 
         `EmployeesJob`.`job_id` 
    FROM `employees` AS `Employee` 
    JOIN `employees_jobs` AS `EmployeesJob` 
         ON (
          `EmployeesJob`.`job_id` = 1 AND 
          `EmployeesJob`.`employee_id` = `Employee`.`id` 
         )
  5. SELECT `Lead`.`id`, `Lead`.`name`, `Lead`.`created` FROM `leads` AS `Lead` 
    WHERE `Lead`.`id` = 4
  6. SELECT `Employee`.`id`, `Employee`.`name`, `Employee`.`created`, 
         `EmployeesJob`.`id`, `EmployeesJob`.`employee_id`, 
         `EmployeesJob`.`job_id` 
    FROM `employees` AS `Employee` 
    JOIN `employees_jobs` AS `EmployeesJob` 
         ON (
          `EmployeesJob`.`job_id` = 1 AND 
          `EmployeesJob`.`employee_id` = `Employee`.`id` 
         )

Обратите внимание, что последние два запроса являются дублирующими. Я сделал что-то не так, что мне не хватает?

UPDATE
кажется Cake посылает дубликат запроса для каждого грузовика. Теперь, когда у меня есть 15 записей в таблице грузовиков, запросы до leads и employees дублируются по 15 раз.

ответ

3

Я не знаю, почему есть два запроса дублированные, но, возможно, это поведение может помочь:

https://github.com/Terr/linkable

UPDATE

Эта проблема хорошо известна:

+0

Это выглядит интригующим. Я проверю это, когда буду работать в понедельник. – Stephen

+0

Awesome, Рио. Спасибо за факт. – Stephen

+0

Так что Билет 2 года. По-видимому, они нацеливаются на CakePHP 2.0, чтобы исправить эту проблему. На данный момент я прибегаю к расщеплению запросов на несколько вызовов на '$ this-> find' и создание массива данных вручную, что отстойно, но это отходит намного меньше, когда вы переходите от 80 запросов к 4 запросам. – Stephen

-3

Вы хотите LEFT JOIN вместо JOIN.

Не спрашивайте меня, как это сделать в cakephp, я рад, что мой код в настоящее время работает. ^^

+0

Вопрос о CakePHP. Хорошего дня, сэр. – Stephen

+0

:: вздох :: Результат - * отлично *. Изменение JOIN не решит проблему. Проблема в том, что CakePHP несколько раз запускает одни и те же запросы. thaRRR11! тебе. – Stephen

+0

Так неправильно ....... – c0rnh0li0

1

Нет ничего, что бы присоединиться к найденному Job/s к определенному Truck.

(я надеюсь, что мое объяснение не слишком трудно понять, но CakePHP может быть так иногда! Имхо)

Jobs в настоящее время отнесены к Trucks в почти произвольным образом (моя память Торт в том, что это может произойти); характер вызова HABTM придает Job/s каждому из 15 Trucks. Это, по-видимому, текущий процесс с моей точки зрения;

  • Получить все грузовики.
  • Получить все вакансии для тех грузовиков, где дата: x.
  • [Проблема 1] Прикрепите найденное Jobs к каждому Truck (то есть вашим 15 грузовикам), но прилагается к каждому Truck.
  • [Проблема 2] Получить все вакансии, связанные с этим Работа, за каждого Truck.

Проблема 1: источник проблемы. Вы можете видеть во втором запросе (SELECT Job ...), где он использует правильный truck_id в инструкции ON, но Cake не может «присоединить» эти Jobs назад вправо Truck, потому что это другой запрос! Таким образом, он присоединяется к найденным работам к каждому Truck.

Задача 2: Это «реальная» проблема, для торта не строит длинные РЕГИСТРИРУЙТЕСЬ заявления, так что нет никакого способа, чтобы найти Employees/Leads только для тех, кто Trucks, что вы хотите. Вот почему он находит их для каждого грузовика, это потому, что вы делаете FindAll на Truck.

Надеюсь, это имеет смысл. Вам нужно найти все на Jobs, так как это 'center' запроса (pickup_date).

$this->loadModel('Job'); 
$whatev = $this->Job->find('all', array(
    'contain' => array(
     'Job' => array(
      'Truck', 
      'Employee', 
      'Lead', 
      'conditions' => array(
       'Job.pickup_date' => $date 
      ) 
     ) 
    ) 
)); 

CakePHP запросы действительно работают только тогда, когда вы найдете один/все определенной модели, то лучше начать в середине и работать с каждой стороны, если у вас есть отношения двойной HABTM. Если вы хотите «сортировать» на Truck, тогда вам, возможно, придется написать собственный запрос (метод модели), чтобы выполнить задачу самостоятельно. В сыром SQL этот запрос может быть легким, в абстрагированном PHP-супер-кексе, для CakePHP это трудно разрешить.

Счастливые выпечки, как говорится!

+0

Это выглядит многообещающим, но вы имели в виду, чтобы содержать Job on Job? – Stephen

+0

У меня есть секрет. Есть еще одно отношение: 'Грузовик -> hasMany -> TruckLog'. (Я просто оставил это из примера для простоты). При перемещении запроса для централизации вокруг 'Job' вместо' Truck', я начинаю получать ту же проблему с 'TruckLog' (запросы дублируются для каждой работы, связанной с грузовиком). – Stephen

+0

Вы правы в отношении Иов, в которых содержится Иов, это был мой контроль. В частности, с дополнительным отношением HABTM TruckLog, вам почти наверняка понадобится создать модельный метод, который найдет именно то, что вы хотите. Вы можете либо запросить SQL-запрос самостоятельно, используя $ Model-> query(), и, возможно, использовать подзапрос/s для достижения этого в одном запросе (скорее всего, быстрее для производительности). Или у вас может быть метод модели, который находит их индивидуально, и использовать слияние массивов (http://book.cakephp.org/view/679/merge) для обработки результатов для каждого элемента. – Ghostpsalm

 Смежные вопросы

  • Нет связанных вопросов^_^