Answers:
我一定会去的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通常调用的任何其他挂钩。加载节点还会调用一些钩子,因此可能效率不高。
如果您有这个想法,并且节点结构简直是简单的话,您也可以这样做:
$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()
让其他模块正确处理字段输入。例如,文件模块使用此钩子将其设置为永久文件状态。我已经更新了上面的2个示例。
node_save
到另一个非常有意义。从3小时更新到40分钟。field_attach_update
EntityFieldQuery
db_query_range
如果您不希望在不引起标准事件和动作发生的情况下保存字段数据,则可以使用drupal_write_record。
这是一个将Hello World插入id为1的article类型的节点的body字段的示例。
$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);
如果您的网站多变,那么您将要使用“ en”或内容的语言而不是“ und”。
如果要进行修订,则必须小心插入正确的修订ID,否则,您可以简单地插入与entity_id相同的值。
请注意如何将此数据插入到两个表field_data_ *和field_revision_ *中。您应该同时插入两者,以确保该站点能够按需工作。
运行此命令后,您将需要清除缓存以使字段显示出来,具体取决于缓存的设置方式。
对于像这样的简单更新,其中需要更新许多节点,我始终使用MySQL更新语句。是的,需要考虑缓存,但是您可以在完成后刷新缓存,这一切都很好。当然,您需要熟悉数据结构,但是在Drupal 6中它相对简单。(尽管在Drupal 7中太可怕了)
我也建议field_attach_update
不要使用直接的SQL查询,因为sql不会更新节点缓存对象,而在下一个中node_load
,您将不会加载更新的字段值,而是会加载旧值
field_attach_update
比直接SQL查询好得多。
stdClass
不加载的情况下将节点创建为对象。您知道如果尝试不设置所有字段就以这种方式更新节点会发生什么情况吗?会被null或默认值覆盖吗?也许这些会在更新过程中被忽略吗?
尝试了其他答案中提到的所有方法后,我的更新时间非常慢(对于具有20多个字段的节点类型的700.000个节点,更新时间约为7天),直到找到本文为止:http : //www.drupalonwindows.com/en/ Blog / only-update-changed-fields-或-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”选项卡执行这样的命令。想象一下,您有一个名为“会员资料”的内容类型。其中有一个名为“成员类型”的字段(例如,公司,个人,组织)。假设您想将所有出现的“ COMPANY”更新为“ company”。下面的命令将执行此操作。
更新content_type_member_profile SET field_type_of_member_value
='company'WHERE field_type_of_member_value
='COMPANY';
另外,请检出MySQL入门
field_attach_update
?