it-swarm.dev

단일 필드 값을 빠르게 저장

내 사이트에 약 70k 개의 지정된 유형의 노드가 있습니다. 그들에 대한 업데이트를 실행해야합니다. 일부 작업 및 하나의 필드를 원하는 값으로 설정 node_save은 실제로 느리고 충돌을 일으 킵니다 (너무 긴 호출 스택 mayby). 이 특정 필드에 정보를 작성하는 더 빠른 방법이 있습니까?

field_attach_update 한 게시물에 언급되었지만 훨씬 빠르지는 않습니다.

편집 :이 노드 유형에 빌드 된 상당히 복잡한 뷰가 있지만 업데이트하려는이 필드에서 작동하지 않습니다.

19
Eloar

나는 확실히 field_attach_update 에 갈 것입니다.

아이디어는 간단하다. 노드를로드하고 field_attach_update를 사용하여 저장하십시오.

전의:

$node = node_load($nid);
$node->field_name[LANGUAGE_NONE][0]['value'] = 'New value';
field_attach_presave('node', $node);
field_attach_update('node', $node);
  // Clear the static loading cache.
entity_get_controller('node')->resetCache(array($node->nid));

이것은 node_save가 일반적으로 호출하는 타임 스탬프 또는 다른 후크를 변경하지 않습니다. 노드를로드하면 일부 후크가 호출되므로 그렇게 효율적이지 않을 수 있습니다.

Nid가 있고 노드 구조가 단순하지 않은 경우 다음과 같이 수행 할 수 있습니다.

 $node = new stdClass();
 $node->nid = $nid; // Enter the nid taken. Make sure it exists. 
 $node->type = 'article';
 $node->field_name[LANGUAGE_NONE][0]['value'] = 'New value';
 field_attach_presave('node', $node);
 field_attach_update('node', $node);
  // Clear the static loading cache.
 entity_get_controller('node')->resetCache(array($node->nid));

어쨌든 필드 이외의 다른 것을 업데이트하려고하면 작동하지 않습니다 (코멘트 상태, 게시 된 상태 등). 또한 node_save를 사용하는 경우 특정 방법에 대한 캐시는 다른 방법으로 자동으로 지워지며 'entity_get_controller'로 지워야합니다.

Update : 다른 모듈이 필드 입력을 올바르게 처리하도록하려면 field_attach_presave()도 호출해야합니다. 예를 들어 파일 모듈은이 후크를 사용하여 파일 상태를 영구로 설정하는 데 사용합니다. 위의 두 가지 예를 업데이트했습니다.

30
AyeshK

다른 답변에 언급 된 모든 접근 방식을 시도한 후에이 기사를 찾을 때까지 업데이트 시간이 매우 느 렸습니다 (20+ 필드가있는 노드 유형의 700.000 노드의 경우 약 7 일) http : //www.drupalonwindows. com/en/blog/only-update-changed-fields-or-properties-entity-drupal .

Hook_update에서 아래 코드와 같은 것을 구현 한 후 업데이트 시간을 2 시간으로 줄였습니다.

if (!isset($sandbox['storage']['nids'])) {
    $sandbox['storage']['nids'] = [];
    $query = 'SELECT {nid} FROM node WHERE type = \'article\';';
    $result = db_query($query)->fetchCol();
    if ($result) {
      $sandbox['storage']['nids'] = $result;
      $sandbox['storage']['total'] = count($sandbox['storage']['nids']);
      $sandbox['storage']['last_run_time'] = time();
      $sandbox['progress'] = 0;
    }
  }

  $amount = 300;
  $nids = array_slice($sandbox['storage']['nids'], 0, $amount);

  if (!empty($nids)) {
    $nodes = node_load_multiple($nids, [], TRUE);
    foreach ($nodes as $node) {
      // Lets manipualte the entity.
      $article_wrapper = UtilsEntity::entity_metadata_wrapper('node', $node);
      // Eventual logic here.

        // Field to update
        $article_wrapper->my_field = 'my_value';
        $article_wrapper->save();

    $sandbox['progress']++;
    }
    $sandbox['message'] = 'Runs left: ' . (($sandbox['storage']['total'] - $sandbox['progress'])/$amount) . ' Progress: ' . (($sandbox['progress'] * $amount)/$sandbox['storage']['total']) . '%';
    $sandbox['storage']['last_run_time'] = time();
    unset($nids);
  }
  $sandbox['storage']['nids'] = array_slice($sandbox['storage']['nids'], 100, count($sandbox['storage']['nids']));
  if (!empty($sandbox['storage']['total'])) {
    $sandbox['#finished'] = ($sandbox['storage']['total'] - count($sandbox['storage']['nids'])) / $sandbox['storage']['total'];
  }
  return $sandbox['message'];
2
dasj19

Sql은 노드 캐시 객체를 업데이트하지 않기 때문에 field_attach_update도 권장하고 직접 SQL 쿼리는 권장하지 않으며 다음 node_load에서는 업데이트 된 필드 값을로드하지 않습니다. 오래된 가치

field_attach_update는 직접 SQL 쿼리보다 훨씬 좋습니다.

2
pico34

표준 이벤트 및 작업이 발생하지 않고 필드 데이터를 저장하지 않으려면 drupal_write_record 를 사용할 수 있습니다.

다음은 id가 1 인 article 유형의 노드에 대한 본문 필드에 Hello World를 삽입하는 예입니다.

$values = array(
  'entity_type' => 'node',
  'bundle' => 'article',
  'entity_id' => 1,
  'revision_id' => 1,
  'language' => 'und',
  'delta' => 0,
  'body_value' => 'HELLO WORLD',
  'body_summary' => '',
  'body_format' => 'filtered_html',
);
drupal_write_record('field_data_body', $values);
drupal_write_record('field_revision_body', $values);

귀하의 사이트가 다국어 인 경우 'und'대신 'en'또는 콘텐츠 언어를 사용하려고합니다.

개정을 수행하는 경우 올바른 개정 ID를 삽입해야합니다. 그렇지 않으면 entity_id와 동일한 값을 삽입 할 수 있습니다.

이 데이터가 field_data_ * 및 field_revision_ * 두 테이블에 삽입되는 방법에 유의하십시오. 사이트가 원하는대로 작동하도록하려면 둘 다에 삽입해야합니다.

이를 실행 한 후 캐싱 설정 방법에 따라 필드가 표시되도록 캐시를 지워야합니다.

2
Thomas4019

많은 노드를 업데이트해야 할 경우 이와 같은 간단한 업데이트를 위해 항상 MySQL 업데이트 문을 사용합니다. 그렇습니다. 캐싱을 고려해야하지만, 완료 한 후에 캐시를 플러시하면됩니다. 물론 데이터 구조에 익숙해야하지만 Drupal 6에서는 비교적 간단합니다.) Drupal 7)

2
Troy Frech

특정 콘텐츠 유형의 모든 노드에 대해 필드를 업데이트해야하는 동일한 요구 사항도있었습니다. node_load_multiplefield_attach_update 를 사용했습니다.

$nodes = node_load_multiple(array(), array('type' => 'content_type_name'));
foreach ($nodes as $node) {
  $node->field_name['und'][0]['value'] = 'field value';
  field_attach_update('node', $node);
}

나는 돌진을 통해 그것을 실행하고 꽤 빠르다.

1
Suresh R

MySQL을 사용하여 데이터베이스로 직접 이러한 업데이트를 수행하는 것을 고려 했습니까? 아마도 원하는 것을 달성하는 가장 간단하고 빠른 방법 일 것입니다.

다음은 간단한 예입니다. phpMyAdmin의 'SQL'탭에서 이러한 명령을 실행할 수 있습니다. 멤버 프로파일이라는 컨텐츠 유형이 있다고 가정하십시오. 여기에는 '회원 유형'(예 : 회사, 개인, 조직)이라는 필드가 있습니다. '회사'에 대한 모든 항목을 '회사'로 업데이트하려고한다고 가정합니다. 다음 명령은 바로 그렇게 할 것입니다.

Content_type_member_profile 업데이트 field_type_of_member_value = '회사'WHERE field_type_of_member_value = '회사';

또한 체크 아웃 MySQL 시작하기

0
Bisonbleu