Recuperare un valore di campo senza caricare l'intero nodo?


11

Ho un gran numero di NID e ho bisogno di un valore di campo da ciascun nodo. C'è un modo per evitare il sovraccarico di caricare l'intero nodo per ottenere un valore di campo?

Risposte:


19

Non penso che ci sia qualcosa di integrato nell'API ma in un pizzico potresti semplicemente interrogare direttamente il database:

$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();

Dopo averlo eseguito, dovresti avere un array di valori di campo, digitato dal rispettivo nid del nodo.

Vale la pena ricordare che il nome della colonna non sarà necessariamente FIELD_NAME_value; ad esempio un campo di riferimento nodo avrebbe un nome di colonna di FIELD_NAME_nid. Quale utilizzerai dipenderà dal tipo di campo.

AGGIORNARE

Sembra che ci sia un modo per farlo con l'API, ma non è carino e comporta ancora una query manuale:

// 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));

Tale metodo sfrutta il $optionsparametro field_attach_load()specificando un ID campo per cui caricare i dati. Vale la pena notare, secondo i documenti:

Si noti che le entità restituite possono contenere dati per altri campi, ad esempio se vengono letti da una cache.

Quindi potrebbe sembrare che il codice carichi ulteriori dati di campo, ma qualsiasi cosa diversa dal campo specificato proviene dalla cache.


Eccezionale. Ha funzionato perfettamente e MOLTO più velocemente del caricamento dell'intero nodo.
Joren,

Ho usato questo approccio con l'entità utente per caricare il valore di un singolo campo ma questo metodo carica tutti i campi (e i loro valori) associati all'oggetto utente. Mi sto perdendo qualcosa?
WM,

Avviso: il primo esempio richiede l'archiviazione dei campi nel database SQL (impostazione predefinita) e non è compatibile con archivi di campi alternativi. Il secondo dovrebbe funzionare (perché usa field_attach_load e funzionerà con l'astrazione delle memorie).
Bobík,

@Clive, c'è qualche motivo per cui hai usato field_revision_FIELD_NAME invece di field_data_FIELD_NAME? Puoi spiegare per favore? Grazie.
Sandesh Yadav,

3

Trovo un modo un po 'più pulito usando un'entitàCondition e un carico di collegamento sul 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');
}

Dal post del blog http://timonweb.com/loading-only-one-field-from-an-entity-or-node


0

Per evitare di caricare uno alla volta il nodo con un numero elevato di NID, è possibile utilizzare node_load_multiple()che caricherà più nodi contemporaneamente:

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

Normalmente il caricamento dei nodi viene memorizzato nella cache ed è veloce se si utilizza la memorizzazione nella cache della memoria (come memcached), ma potrebbe essere lento se sono stati installati troppi moduli (come Pathauto, ecc.).

L'altro modo è riutilizzare l'oggetto esistente, quindi controlla se è possibile caricarlo direttamente dalla cache (ad esempio tramite form_get_cachese fa parte del modulo) o dalla $_POSTrichiesta.

Un altro modo è utilizzare EntityFieldQuerycon più NID, ad es

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

che recupererà i valori direttamente dal database.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.