รับค่าเขตข้อมูลโดยไม่ต้องโหลดโหนดทั้งหมดหรือไม่


11

ฉันมี NID จำนวนมากและฉันต้องการค่าฟิลด์หนึ่งค่าจากแต่ละโหนด มีวิธีใดที่จะหลีกเลี่ยงโอเวอร์เฮดของการโหลดทั้งโหนดเพื่อรับค่าฟิลด์หนึ่งค่าหรือไม่?

คำตอบ:


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ตัวอย่างเช่นสนามโหนดอ้างอิงจะมีชื่อคอลัมน์ของ รูปแบบที่คุณใช้จะขึ้นอยู่กับประเภทเขตข้อมูลของคุณ

UPDATE

ดูเหมือนว่ามีวิธีที่จะทำกับ 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));

วิธีการดังกล่าวใช้ประโยชน์จาก$optionsพารามิเตอร์field_attach_load()โดยระบุ ID ฟิลด์เพื่อโหลดข้อมูล เป็นที่น่าสังเกตว่าต่อเอกสาร:

โปรดทราบว่าเอนทิตีที่ส่งคืนอาจมีข้อมูลสำหรับเขตข้อมูลอื่นตัวอย่างเช่นถ้าพวกเขาอ่านจากแคช

ดังนั้นรหัสอาจปรากฏขึ้นเพื่อโหลดข้อมูลเขตข้อมูลพิเศษ แต่สิ่งอื่นใดนอกเหนือจากเขตข้อมูลที่คุณระบุจะมาจากแคช


น่ากลัว ทำงานได้อย่างสมบูรณ์แบบและรวดเร็วกว่าการโหลดทั้งโหนด
Joren

ฉันใช้วิธีนี้กับเอนทิตีผู้ใช้เพื่อโหลดค่าของเขตข้อมูลเดียว แต่วิธีนี้จะโหลดเขตข้อมูลทั้งหมด (และค่าของพวกเขา) ที่เกี่ยวข้องกับวัตถุผู้ใช้ ฉันพลาดอะไรไปรึเปล่า?
WM

คำเตือน: ตัวอย่างแรกต้องการเก็บเขตข้อมูลในฐานข้อมูล SQL (ค่าเริ่มต้น) และเข้ากันไม่ได้กับการจัดเก็บข้อมูลทางเลือก ที่สองควรทำงาน (เพราะมันใช้ field_attach_load และมันจะทำงานกับการเก็บรักษานามธรรม)
Bobík

@Clive มีเหตุผลใดที่คุณใช้ field_revision_FIELD_NAME แทนที่จะเป็น field_data_FIELD_NAME คุณช่วยอธิบายได้มั้ย ขอบคุณ
Sandesh Yadav

3

ฉันพบวิธีที่สะอาดขึ้นโดยใช้ entityCondition และ field Attach load

$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 ที่มีจำนวนมากคุณสามารถใช้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.