답변:
나는 확실히 갈 것이다 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'로 지워야합니다.
업데이트 :field_attach_presave()
다른 모듈이 필드 입력을 올바르게 처리하도록
호출해야합니다 . 예를 들어 파일 모듈은이 후크를 사용하여 파일 상태를 영구로 설정하는 데 사용합니다. 위의 두 가지 예를 업데이트했습니다.
node_save
에 field_attach_update
와에서 EntityFieldQuery
에 db_query_range
확실히 보답했다. 3 시간 업데이트에서 40 분
표준 이벤트 및 조치가 발생하지 않고 필드 데이터를 저장하지 않으려면 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_ * 두 테이블에 어떻게 삽입되는지 참고하십시오. 사이트가 원하는대로 작동하도록하려면 둘 다에 삽입해야합니다.
이를 실행 한 후 캐싱 설정 방법에 따라 필드가 표시되도록 캐시를 지워야합니다.
많은 노드를 업데이트해야 할 경우 이와 같은 간단한 업데이트를 위해 항상 MySQL 업데이트 문을 사용합니다. 그렇습니다. 캐싱을 고려해야하지만 완료 후에 캐시를 플러시하면됩니다. 물론 데이터 구조에 익숙해야하지만 Drupal 6에서는 비교적 간단합니다 (Drupal 7에서는 끔찍하지만).
field_attach_update
SQL은 노드 캐시 객체를 업데이트하지 않기 때문에 직접 SQL 쿼리가 아니라도 제안 합니다. 다음 node_load
에 업데이트 된 필드 값을로드하지 않으면 이전 값을로드합니다.
field_attach_update
직접 SQL 쿼리보다 훨씬 낫습니다.
stdClass
로드하지 않고 객체로 노드를 생성 할 것을 제안했습니다 . 모든 필드를 설정하지 않고이 방법으로 노드를 업데이트하려고하면 어떤 일이 발생할 수 있는지 알고 있습니까? 그것들을 널이나 기본값으로 덮어 쓸 것인가? Mayby는 프로세스를 업데이트하여 무시됩니까?
다른 답변에 언급 된 모든 접근 방식을 시도한 결과이 기사를 찾을 때까지 업데이트 시간이 매우 느 렸습니다 (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'];
특정 콘텐츠 유형의 모든 노드에 대해 필드를 업데이트해야하는 동일한 요구 사항도있었습니다. node_load_multiple 과 field_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);
}
나는 돌진을 통해 그것을 실행하고 꽤 빠르다.
mySQL을 사용하여 데이터베이스로 직접 이러한 업데이트를 수행하는 것을 고려 했습니까? 아마도 원하는 것을 달성하는 가장 간단하고 빠른 방법 일 것입니다.
다음은 간단한 예입니다. phpMyAdmin의 'SQL'탭에서 이러한 명령을 실행할 수 있습니다. 멤버 프로파일이라는 컨텐츠 유형이 있다고 가정하십시오. 여기에는 '회원 유형'(예 : 회사, 개인, 조직)이라는 이름의 필드가 있습니다. '회사'에 대한 모든 항목을 '회사'로 업데이트하려고한다고 가정합니다. 다음 명령은 바로 그렇게 할 것입니다.
content_type_member_profile 업데이트 SET field_type_of_member_value
= 'company'WHERE field_type_of_member_value
= '회사';
또한 Checkout MySQL 시작하기
field_attach_update
있습니까?