ノード全体をロードせずにフィールド値を取得しますか?


11

多数のNIDがあり、各ノードから1つのフィールド値が必要です。1つのフィールド値を取得するためにノード全体をロードするオーバーヘッドを回避する方法はありますか?

回答:


19

APIには何も組み込まれていないと思いますが、簡単に言えば、データベースを直接クエリするだけです。

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

これを実行すると、それぞれのノードのnidでキー設定されたフィールド値の配列が得られます。

列名は必ずしもそうであるとは限らないことに注意してくださいFIELD_NAME_value。たとえば、ノード参照フィールドの列名はになりFIELD_NAME_nidます。どちらを使用するかは、フィールドタイプによって異なります。

更新

APIでそれを行う方法があるようですが、それはきれいではなく、手動のクエリがまだ含まれています:

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

このメソッドは、データをロードするフィールドIDを指定することで、$optionsパラメーターを利用しますfield_attach_load()。ドキュメントごとに、それは注目に値します:

キャッシュから読み取られた場合など、返されたエンティティには他のフィールドのデータが含まれる場合があることに注意してください。

そのため、コードは余分なフィールドデータをロードしているように見えたかもしれませんが、指定したフィールド以外のものはすべてキャッシュから取得されます。


驚くばかり。ノード全体をロードするよりも完全に、はるかに速く動作しました。
Joren

このアプローチをユーザーエンティティで使用して単一のフィールドの値をロードしましたが、このメソッドはユーザーオブジェクトに関連付けられたすべてのフィールド(およびそれらの値)をロードします。何か不足していますか?
WM

警告:最初の例では、SQLデータベースにフィールドを格納する必要があり(デフォルト)、代替のフィールドストレージと互換性がありません。2番目は機能するはずです(field_attach_loadを使用し、ストレージの抽象化で機能するため)。
Bobík

@Clive、field_data_FIELD_NAMEの代わりにfield_revision_FIELD_NAMEを使用した理由はありますか?説明していただけますか?ありがとう。
Sandesh Yadav

3

私は、entityConditionとフィールド接続ロードを使用して少しすっきりとした方法を見つけました。

$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');
}

ブログ投稿http://timonweb.com/loading-only-one-field-from-an-entity-or-node


0

多数のNIDを持つノードを1つずつロードしないようにするには、次のコマンドを使用しnode_load_multiple()て、一度に複数のノードをロードします。

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

通常、ノードのロードはキャッシュされ、メモリキャッシング(memcachedなど)を使用している場合は高速ですが、インストールされているモジュール(Pathautoなど)が多すぎる場合は遅くなる可能性があります。

他の方法は、既存のオブジェクトを再利用することです。そのため、オブジェクトをキャッシュから直接(たとえばform_get_cache、フォームの一部である場合)、または$_POST要求からロードできるかどうかを確認してください。

別の方法はEntityFieldQuery、複数のNIDで使用することです。たとえば、

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

データベースから直接値をフェッチします。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.