Recuperar um valor de campo sem carregar o nó inteiro?

11

Eu tenho um grande número de NIDs e preciso de um valor de campo de cada nó. Existe alguma maneira de evitar a sobrecarga de carregar o nó inteiro para obter um valor de campo?

Joren
fonte

Respostas:

19

Eu não acho que exista algo incorporado à API, mas em uma pitada você pode simplesmente consultar o banco de dados diretamente:

$entity_type = 'node';
$bundle = 'page';
$nids = array(1, 2, 3);

$field_values = db_select('field_revision_FIELD_NAME', 'f')
  ->fields('f', array('entity_id', 'FIELD_NAME_value'))
  ->condition('entity_type', $entity_type)
  ->condition('bundle', $bundle)
  ->condition('entity_id', $nids, 'IN')
  ->condition('deleted', 0)
  ->execute()
  ->fetchAllKeyed();

Após a execução, você deverá ter uma matriz de valores de campo, codificada pelo nid do respectivo nó.

Vale lembrar que o nome da coluna não será necessariamente FIELD_NAME_value; por exemplo, um campo de referência de nó teria um nome de coluna de FIELD_NAME_nid. Qual você usará dependerá do seu tipo de campo.

ATUALIZAR

Parece que existe uma maneira de fazer isso com a API, mas não é bonito e ainda envolve uma consulta manual:

// Get the field meta data for the field_id.
$field_name = 'field_something';
$field_info = field_info_field($field_name);
$field_id = $field_info['id'];

// Load up the properties from the node table.
$nids = array(1, 2, 3);
$sql = 'SELECT * FROM {node} WHERE nid IN (:nids)';
$nodes = db_query($sql, array(':nids' => $nids))->fetchAllAssoc('nid');

// Attach the single field to all nodes.
field_attach_load('node', $nodes, FIELD_LOAD_CURRENT, array('field_id' => $field_id));

Esse método aproveita o $optionsparâmetro field_attach_load()especificando um ID de campo para o qual carregar dados. Vale a pena notar, de acordo com os documentos:

Observe que as entidades retornadas podem conter dados para outros campos, por exemplo, se forem lidos em um cache.

Portanto, o código pode parecer carregar dados de campo extras, mas qualquer coisa que não seja o campo especificado será proveniente do cache.

Clive
fonte
Impressionante. Funcionou perfeitamente e MUITO mais rápido do que carregar o nó inteiro.
Joren
Eu usei essa abordagem com a entidade de usuário para carregar o valor de um único campo, mas esse método carrega todos os campos (e seus valores) associados ao objeto de usuário. Estou esquecendo de algo?
WR
Aviso: O primeiro exemplo requer o armazenamento de campos no banco de dados SQL (padrão) e não é compatível com armazenamentos de campos alternativos. O segundo deve funcionar (porque usa field_attach_load e funcionará com a abstração de armazenamento).
Bobík 17/11/16
@Clive, existe algum motivo pelo qual você usou field_revision_FIELD_NAME em vez de field_data_FIELD_NAME? Você pode explicar, por favor? Obrigado.
Sandesh Yadav
3

Acho uma maneira um pouco mais limpa usando uma entidadeCondição e carga de anexação de campo.

$query = new EntityFieldQuery();
$query->entityCondition('entity_type', 'node')
  ->entityCondition('bundle', 'story')
  ->propertyCondition('status', 1)
  ->fieldCondition('field_story_image', 'fid', 'NULL', '!=');
$result = $query->execute();

if (isset($result['node'])) {
  $stories = $result['node'];

  // At first we need to get field's id. If you already know field id, you can ommit this step
  // Get all fields attached to a given node type
  $fields = field_info_instances('node', 'story');

  // Get id of body field
  $field_id = $fields['field_story_image']['field_id'];

  // Attach a field of selected id only to get value for it
  field_attach_load('node', $stories, FIELD_LOAD_CURRENT, array('field_id' => $field_id));

  // Get values of our node field
  $output = field_get_items('node', $stories, 'field_story_image');
}

Na postagem do blog http://timonweb.com/loading-only-one-field-from-an-entity-or-node

Gagarine
fonte
0

Para evitar carregar o nó um por um com um grande número de NIDs, você pode usar o node_load_multiple()que carregará vários nós de uma só vez:

node_load_multiple($nids = array(), $conditions = array(), $reset = FALSE)

Normalmente, o carregamento dos nós é armazenado em cache e é rápido se você estiver usando o cache de memória (como memcached), mas pode ser lento se você tiver muitos módulos instalados (como Pathauto, etc.).

Outra maneira é reutilizar o objeto existente, portanto verifique se você pode carregá-lo diretamente do cache (por exemplo, via form_get_cachese faz parte do formulário) ou da $_POSTsolicitação.

Outra maneira é usar EntityFieldQuerycom vários NIDs, por exemplo

$query->entityCondition('entity_id', array(17, 21, 422), 'IN')

que buscará os valores diretamente do banco de dados.

kenorb
fonte