XPDO ресурсы и связанные TV в одном объекте

Пытаюсь сделать выборку на xPDO сложнее чем в примерах для обучения. Сформировать объект при помощи xPDO содержащий все поля ресурса + его TV и записать в XML.

Есть ресурсы, выбираем те, у которых parent равен определенному id. при этом в объект надо прикрепить все TV поля этого ресурса. пробуем достать граф. modResource — для полей ресурса, TemplatevarResources — связь для получения many TVшек, и TemplateVar связь для получения имени TV.

$c = $modx->newQuery('modResource');
$c->where(array(
 		 'parent' => '30'
		));
$resources = $modx->getCollectionGraph('modResource', '{
  "TemplateVarResources":{ "TemplateVar":{} } }',$c);
На тестовом сайте чуть меньше 1000 ресурсов, при выполнении данного скрипта в консоли получаем ошибку
Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 8192 bytes)
Мы сожрали всю память.

Ставим лимит 100, в
$resources
падает только 4 штуки. (хотя по идее он должен был вывести 100 штук) при увеличении число растет, но не упирается в лимит.

При доступе к связанным объектам графа вообще в переменных код сниппетов вижу.

Что не так с getCollectionGraph в моем случае?

p.s. для чего это надо? При вызове $resource-getTVValue(x) для каждого ТВ, Мы обращаемся к БД. И если у нас 700 ресурсов по 50 tv параметров, то получаем 35000 отдельных запросов.
Vladimir Alekhin
05 марта 2018, 11:50
modx.pro
2 001
0

Комментарии: 4

Наумов Алексей
05 марта 2018, 14:56
0
Дабы память не сошла с ума — дергайте их по 1-му в цикле.

Хотите оптимизации — делайте запросы руками, механизмы типа getCollectionGraph 100% жутко прожорливы.
    Vladimir Alekhin
    05 марта 2018, 15:08
    0
    Вопрос в другом, даже с лимитом в 1
    $c->limit(100);

    У меня не получается достучаться до значения, имени и ид всех ТВ ресурса.
    Если мы добавим после вызова Графа

    foreach ($resources as $resource) {
        $count++;
        if ($resource->TemplateVarResources) {
            foreach ($resource->getMany('TemplateVarResources') as $tvs) {
    		print_r($tvs);
    		}
    Я не получаю Объект содержащий все привязанные к данному ресурсу ТВшки.

    Дабы память не сошла с ума — дергайте их по 1-му в цикле.
    Выполнить сначала GetCount что бы посчитать их количество и идти циклом?
    Андрей
    06 марта 2018, 09:26
    0
    В $data будут все поля ресурса, все его тв со значениями и именами

    $q = $modx->newQuery('modResource');
    $q->leftJoin('modTemplateVarResource', 'TVR', 'TVR.contentid = modResource.id');
    $q->leftJoin('modTemplateVar', 'TV', 'TV.id = TVR.tmplvarid');
    $q->where([
     'modResource.parent' => 30
    ]);
    $q->select([
     'modResource.*',
     'TVR.*',
     'TV.*'
    ]);
    
    if ($q->prepare() && $q->stmt->execute()) {
      $data = $q->stmt->fetchAll(PDO::FETCH_ASSOC);
    }
    
    print_r($data);

    Обратите внимание, что если у ресурса есть tv со значением по-умолчанию и оно не заполнено, либо установлено значение по-умолчанию, в выборке его не будет, т.к. MODX не создает записей modTemplateVarResource в базе для значений по-умолчанию.
      Vladimir Alekhin
      14 марта 2018, 15:02
      0
      Было решено делать выборку на стороне СУБД при помощи подобного запроса.
      $result = $modx->query("
      
      SELECT 
      		t.id,
      		t.pagetitle,
      		t.createdon,
      		t.content,
      		GROUP_CONCAT(t.idea_date_tech) AS idea_date_tech,
      		GROUP_CONCAT(t.idea_status) AS idea_status,
      		GROUP_CONCAT(t.idea_status_info) AS idea_status_info,
      		GROUP_CONCAT(t.idea_type) AS idea_type,
      		GROUP_CONCAT(t.idea_internal_status) AS idea_internal_status,
      		GROUP_CONCAT(t.idea_category) AS idea_category,
      		GROUP_CONCAT(t.idea_need_money) AS idea_need_money,
      		GROUP_CONCAT(t.idea_start_date_plan) AS idea_start_date_plan,
      		GROUP_CONCAT(t.idea_end_date_plan) AS idea_end_date_plan,
      		GROUP_CONCAT(t.idea_start_date_fact) AS idea_start_date_fact,
      		GROUP_CONCAT(t.idea_end_date_fact) AS idea_end_date_fact,
      		GROUP_CONCAT(t.idea_geteconom_IQ) AS idea_geteconom_IQ,
      		GROUP_CONCAT(t.idea_geteconom_IIQ) AS idea_geteconom_IIQ,
      		GROUP_CONCAT(t.idea_geteconom_IIIQ) AS idea_geteconom_IIIQ,
      		GROUP_CONCAT(t.idea_geteconom_IVQ) AS idea_geteconom_IVQ,
      		GROUP_CONCAT(t.idea_geteconom_total) AS idea_geteconom_total,
      		GROUP_CONCAT(t.idea_cureeconom_IQ) AS idea_cureeconom_IQ,
      		GROUP_CONCAT(t.idea_cureeconom_IIQ) AS idea_cureeconom_IIQ,
      		GROUP_CONCAT(t.idea_cureeconom_IIIQ) AS idea_cureeconom_IIIQ,
      		GROUP_CONCAT(t.idea_cureeconom_IVQ) AS idea_cureeconom_IVQ,
      		GROUP_CONCAT(t.idea_cureeconom_total) AS idea_cureeconom_total,
      		GROUP_CONCAT(t.idea_in_concurs) AS idea_in_concurs,
      		GROUP_CONCAT(t.idea_concurs_date) AS idea_concurs_date,
      		GROUP_CONCAT(t.idea_concurs_result) AS idea_concurs_result,
      		GROUP_CONCAT(t.idea_prem_IQ) AS idea_prem_IQ,
      		GROUP_CONCAT(t.idea_prem_IIQ) AS idea_prem_IIQ,
      		GROUP_CONCAT(t.idea_prem_IIIQ) AS idea_prem_IIIQ,
      		GROUP_CONCAT(t.idea_prem_IVQ) AS idea_prem_IVQ,
      		GROUP_CONCAT(t.idea_prem_total) AS idea_prem_total,		
      		GROUP_CONCAT(t.departament) AS departament,
      		t.longtitle,
      		
      		GROUP_CONCAT(t.function) AS function,
      		GROUP_CONCAT(t.phone) AS phone ,
      		t.published
      	FROM (
      			SELECT c.id, c.pagetitle, c.createdon, c.content,
      
      			CASE cv.tmplvarid
      			 WHEN 18 THEN cv.value 
      			END
      			AS idea_date_tech,
      
      			CASE cv.tmplvarid
      			 WHEN 15 THEN cv.value 
      			END
      			AS idea_status,
      			
      			CASE cv.tmplvarid
      			 WHEN 19 THEN cv.value 
      			END
      			AS idea_status_info,
      			
      			CASE cv.tmplvarid
      			 WHEN 20 THEN cv.value 
      			END
      			AS idea_type,
      			
      			CASE cv.tmplvarid
      			 WHEN 46 THEN cv.value 
      			END
      			AS idea_internal_status,
      			
      			CASE cv.tmplvarid
      			 WHEN 45 THEN cv.value 
      			END
      			AS idea_category,
      			
      			CASE cv.tmplvarid
      			 WHEN 47 THEN cv.value 
      			END
      			AS idea_need_money,
      
      			CASE cv.tmplvarid
      			 WHEN 21 THEN cv.value 
      			END
      			AS idea_start_date_plan,
      			
      			CASE cv.tmplvarid
      			 WHEN 22 THEN cv.value 
      			END
      			AS idea_end_date_plan,
      			
      			CASE cv.tmplvarid
      			 WHEN 23 THEN cv.value 
      			END
      			AS idea_start_date_fact,
      			
      			CASE cv.tmplvarid
      			 WHEN 24 THEN cv.value 
      			END
      			AS idea_end_date_fact,
      			
      			CASE cv.tmplvarid
      			 WHEN 25 THEN cv.value 
      			END
      			AS idea_geteconom_IQ,
      			
      			CASE cv.tmplvarid
      			 WHEN 26 THEN cv.value 
      			END
      			AS idea_geteconom_IIQ,
      			
      			CASE cv.tmplvarid
      			 WHEN 27 THEN cv.value 
      			END
      			AS idea_geteconom_IIIQ,
      			
      			CASE cv.tmplvarid
      			 WHEN 28 THEN cv.value 
      			END
      			AS idea_geteconom_IVQ,
      			
      			CASE cv.tmplvarid
      			 WHEN 29 THEN cv.value 
      			END
      			AS idea_geteconom_total,
      			
      			CASE cv.tmplvarid
      			 WHEN 31 THEN cv.value 
      			END
      			AS idea_cureeconom_IQ,
      			
      			CASE cv.tmplvarid
      			 WHEN 32 THEN cv.value 
      			END
      			AS idea_cureeconom_IIQ,
      			
      			CASE cv.tmplvarid
      			 WHEN 33 THEN cv.value 
      			END
      			AS idea_cureeconom_IIIQ,
      			
      			CASE cv.tmplvarid
      			 WHEN 34 THEN cv.value 
      			END
      			AS idea_cureeconom_IVQ,
      			
      			CASE cv.tmplvarid
      			 WHEN 35 THEN cv.value 
      			END
      			AS idea_cureeconom_total,
      			
      			CASE cv.tmplvarid
      			 WHEN 36 THEN cv.value 
      			END
      			AS idea_in_concurs,
      			
      			CASE cv.tmplvarid
      			 WHEN 38 THEN cv.value 
      			END
      			AS idea_concurs_date,
      			
      			CASE cv.tmplvarid
      			 WHEN 39 THEN cv.value 
      			END
      			AS idea_concurs_result,
      			
      			CASE cv.tmplvarid
      			 WHEN 40 THEN cv.value 
      			END
      			AS idea_prem_IQ,
      			
      			CASE cv.tmplvarid
      			 WHEN 41 THEN cv.value 
      			END
      			AS idea_prem_IIQ,
      			
      			CASE cv.tmplvarid
      			 WHEN 42 THEN cv.value 
      			END
      			AS idea_prem_IIIQ,
      			
      			CASE cv.tmplvarid
      			 WHEN 43 THEN cv.value 
      			END
      			AS idea_prem_IVQ,
      			
      			CASE cv.tmplvarid
      			 WHEN 44 THEN cv.value 
      			END
      			AS idea_prem_total,
      			
      			
      			CASE cv.tmplvarid
      			 WHEN 14 THEN cv.value 
      			END
      			AS departament,
      			
      			c.longtitle,
      			
      			CASE cv.tmplvarid
      			 WHEN 16 THEN cv.value 
      			END
      			AS function, 
      			
      			CASE cv.tmplvarid
      			 WHEN 17 THEN cv.value 
      			END
      			AS phone, 
      
      			c.published
      
      			FROM modx_site_content c 
      			left join modx_site_tmplvar_contentvalues cv on c.id = cv.contentid 
      			inner join modx_site_tmplvars tv on cv.tmplvarid = tv.id 
      			where c.parent = 30
      		) t 
      GROUP BY t.id
      order by t.pagetitle;
      
      ");
      
          
         $resources = $result->fetchall(PDO::FETCH_ASSOC);
      Не знаю на сколько решение элегантное, но так мы не тянем те поля ресурса, что нам не нужны в память. работает быстро.
        Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
        4