hızlı tasarruflu tek alan değeri


19

Sitemde belirtilen türde yaklaşık 70 bin düğüm var. Onları güncellemem gerekiyor. Bazı işlemler ve bir alanın istenen değere ayarlanması. node_savegerçekten yavaştır ve çökmelere neden olur (çok uzun calltack mayby). Bu özel alana bilgi yazmanın daha hızlı bir yolu var mı?

Bir gönderide field_attach_updatebahsedildi, ancak çok daha hızlı değil.

EDIT: Bu düğüm türü üzerinde oldukça karmaşık bir görünüm var, ancak güncelleştirmek istediğim bu alanda çalışmıyor.

Yanıtlar:


30

Kesinlikle giderdim field_attach_update.

Fikir basit. Düğümü yükleyin ve field_attach_update öğesini kullanarak kaydedin.

Ör:

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

Bu, node_save işlevinin genellikle çağırdığı hiçbir zaman damgasını veya başka bir kancayı değiştirmez. Düğümü yüklemek de bazı kancaları çağıracaktır, bu yüzden muhtemelen o kadar verimli değildir.

Nid değerine sahipseniz ve düğüm yapısı basitse, bunu şu şekilde de yapabilirsiniz:

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

Her neyse, alanlar dışında bir şey güncellemeye çalışıyorsanız, bu işe yaramaz (yorum durumu, yayınlanmış durum, vb.). Ayrıca node_save kullanıyorsanız, belirli bir düğümün önbelleği, 'entity_get_controller' ile temizlememiz gereken farklı yöntemler için otomatik olarak temizlenir.

Güncelleme: Görünüşe göre, field_attach_presave()diğer modüllerin alan girişini doğru şekilde işlemesine izin vermeniz gerekir . Örneğin dosya modülü, bu kancayı kullanarak dosya durumunu kalıcı olarak ayarlamak için kullanır. Yukarıdaki 2 örneğimi güncelledim.


Nid var ama yapısı düğüm için o kadar basit değil, ama güncellemek istediğim alan çok basit. Ne var (nid tarafından tanımlanan ancak yüklü değil) mevcut düğüm için sadece bir alan ayarlama ve sonra arama bekleyebilirsiniz field_attach_update?
Eloar

4
Varlık sorgusu kullanarak ortaya çıktı gibi şeyler yavaşlatıyordu. Geçiş Yani node_saveetmek field_attach_updateve gelen EntityFieldQueryiçin db_query_rangeoldukça ödüllendirici oldu. 3 saatten 40 dakikaya kadar.
Eloar

2

Standart olayların ve eylemlerin gerçekleşmesine neden olmadan alan verilerini kaydetmek istemiyorsanız, drupal_write_record kullanabilirsiniz .

Burada, 1 numaralı kimliğe sahip bir yazı tipi düğümü için gövde alanına Hello World eklemek için bir örnek verilmiştir.

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

Siteniz çok dilli ise 'und' yerine 'en' veya içeriğinizin dilini kullanmak istersiniz.

Düzeltme yapıyorsanız, doğru düzeltme kimliğini girmeye dikkat etmeniz gerekir, aksi takdirde entity_id ile aynı değeri girebilirsiniz.

Bu verilerin field_data_ * ve field_revision_ * tablolarına nasıl eklendiğine dikkat edin. Sitenin istediğiniz gibi çalıştığından emin olmak için her ikisine de eklemeniz gerekir.

Bunu çalıştırdıktan sonra, önbelleğinizin nasıl kurulduğuna bağlı olarak alanların görünmesi için önbellekleri temizlemeniz gerekir.


2

Birçok düğümün güncellenmesi gereken böyle basit bir güncelleme için her zaman bir MySQL güncelleme ifadesi kullanıyorum. Evet, önbelleğe almanın dikkate alınması gerekir, ancak bitirdikten sonra önbelleği temizleyebilirsiniz ve hepsi iyidir. Tabii ki, veri yapısına aşina olmanız gerekir, ancak Drupal 6'da nispeten basittir (Drupal 7'de korkunç olmasına rağmen)


Proje Drupal 7 için oluşturuldu. Modülümün bazı bölümleri, değerleri okumak ve sql sorguları aramak için doğrudan Drupal DB yapısında manipüle etmek için yapıldıktan sonra EntityFieldQueries'den çok daha hızlıydı.
Eloar

2

Ben field_attach_updatede doğrudan SQL sorgusu değil, önermek , çünkü sql düğüm önbellek nesnesini güncellemez ve bir sonraki node_loadgüncellenen alan değerini yüklemek olmaz, eski değeri yükleyeceksiniz

field_attach_update doğrudan SQL sorgusundan çok daha iyidir.


Ayesh K stdClass, yük olmadan nesne olarak düğüm oluşturmayı önerdi . Tüm alanları ayarlamadan düğümü bu şekilde güncellemeye çalışırsam ne olabileceğini biliyor musunuz? Bunların üzerine null veya default'lar yazılır mı? Güncelleme işlemi ile bunlar göz ardı edilebilir mi?
Eloar

1
Bir düğümü doğrudan Ayeshs yöntemiyle (yeni stdClass vb ...) kaydetmek mümkündür, yalnızca UI gerekli alanlarda doğrulama yapar
pico34

Tüm alanları ayarlamadan düğümü bu yöntemle güncellemeye çalışacağım ve ne olacağını kontrol edeceğim. Modül güncelleme prosedüründe (toplu) düğümleri güncellemek için en hızlı yöntem olabilir.
Eloar

2

Diğer cevaplarda bahsedilen tüm yaklaşımları denedikten sonra, bu makaleyi bulana kadar çok yavaş güncelleme süreleri aldım (20+ alana sahip 700.000 düğüm düğümü için yaklaşık 7 gün): http://www.drupalonwindows.com/tr/ blog / only-update-change-fields-or-properties-entity-drupal .

Hook_update içinde aşağıdaki kod gibi bir şey uyguladıktan sonra güncelleme süresini 2 saate düşürdüm, bu da yönetilebilir olduğunu düşünüyorum.

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'];

1

Hatta belirli bir içerik türünün tüm düğümleri için bir alanı güncelleme gereksinimim vardı. Kullandığım node_load_multiple ve 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);
}

Ben acele koştu ve oldukça hızlı oldu.


0

Bu güncellemeleri mySQL kullanarak doğrudan veritabanına yapmayı düşündünüz mü? Muhtemelen istediğini elde etmenin en basit ve en hızlı yolu.

İşte basit bir örnek. Böyle bir komutu phpMyAdmin'deki 'SQL' sekmesinden yürütebilirsiniz. Üye Profili adında bir içerik türünüz olduğunu düşünün. İçinde 'Üye türü' (ör. Şirket, birey, kuruluş) adında bir alanınız var. 'ŞİRKET' için tüm tekrarları 'şirket' olarak güncellemek istediğinizi varsayalım. Aşağıdaki komut bunu yapacaktır.

UPDATE content_type_member_profile SET field_type_of_member_value= 'şirket' NEREDE field_type_of_member_value= 'ŞİRKET';

Ayrıca, ödeme MySQL ile Başlayın


Seçeneklerden biridir. Kontrol etmek ve uygulamak için sonuncusu olarak bırakıyorum. Drupal yapıyı ve kusurları fazla karıştırmak istemiyorum. Öncelikle doğrudan Drupal API aracılığıyla herhangi bir çözüm arıyorum. Bazı örnekler verebilirseniz çok memnun oluruz.
Eloar

Google noktası. İlk cevabıma basit bir örnek ekledim.
Bisonbleu

eh, SQL herhangi bir tablodaki kayıtları güncelleştirmek için yeterince iyi biliyorum. Sorun değil. Sorun şu ki, drupal'ın veri depolamasına (özellikle meta-veriye) yeterince aşina değilim. Bu tür sistemlerde her zaman çok fazla önbellekleme, koruma ve benzeri vardır, bu nedenle en düşük düzeyde güncellenmesi (her zaman değil) bazı kusurları kirletebilir. Eğer buna geldiyse, bunu en düşük seviyede yapmaya çalışacağım ve gerçek bir karmaşaya hazır olacağım.
Eloar
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.