Получить имя тега (термина) для нескольких узлов без снижения производительности


Я хочу получить список узлов и вернуть их в формате JSON вместе с их тегами (включая имена). После долгих исследований я пришел только к такому решению:

У меня есть массив узлов (\Drupal\Core\Entity\EntityInterface), загруженный Node::loadMultiple().

Перебор массива узлов и получение их тегов с использованием $node->field_tags (или независимо от имени машины тегов), что дает массив \Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem

Получение всех терминов узла с помощью Term::loadMultiple(), а затем повторение их и получение имени с помощью $term->name[0]->value.

Проблема в том, что для каждого узла есть дополнительная база данных для чтения, и я предполагаю, что основным запросом для этого чтения является СОЕДИНЕНИЕ:|.

Вопрос: Существует ли эффективный способ загрузки имен тегов (терминов) вместе с target_id, target_type, target_uuid, и т.д.? Если нет, то является ли текущий цикл на каждом узле правильным путем???

Дополнительная Информация:

  • Я разбиваю результаты на страницы
  • Клиент может установить количество результаты на страницу, но есть ограничение в 50 узлов на страницу

Спасибо

P.S.: У меня есть еще два типа тегов, поэтому мне нужно сделать это еще два раза. Яркая сторона в том, что два других тега - 1to1.

Author: Milad.Nozari, 2017-11-26

1 answers

Если вы уже перебираете массив узлов, рассматривали ли вы возможность сбора идентификаторов терминов перед их загрузкой в один запрос? Это должно сэкономить много накладных расходов при выполнении нескольких запросов:

$map = [];
$tids = [];

// Collect IDs for each node:
/** @var \Drupal\node\Entity\NodeInterface[] $nodes */
foreach ($nodes as $nid => $node) {
  /** @var \Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem $item */
  foreach ($node->field_tags as $item) {
    $tid = $item->target_id;
    $map[$nid][$tid] = $tid;
    $tids[$tid] = $tid;
  }
}

// Load terms and collect their labels:
$term_labels = [];
/** @var \Drupal\taxonomy\Entity\TermInterface $term */
foreach (Term::loadMultiple($tids) as $tid => $term) {
  $term_labels[$tid] = $term->label();
}

// Assign the term labels to each node.
foreach ($map as $nid => $node_tids) {
  foreach ($node_tids as $tid) {
    $map[$nid][$tid] = $term_labels[$tid];
  }
}
 3
Author: Christoph Burschka, 2017-11-26 16:34:03