Puncte:0

Folosind migrate (de asemenea) pentru a actualiza nodurile care există deja în Drupal

drapel cn

Sunt în curs de portare a unei baze de date non-Drupal în Drupal 9. Baza de date originală conține, printre altele, un tabel de Cărți (cu informațiile obișnuite) și un tabel separat (nu mă întrebați de ce) pentru Cărți de călătorie. Primul are 10.000 de înregistrări și a fost migrat cu succes de la un cărți.csv către Drupal. Acesta din urmă (cărți de călătorie.csv) este de doar 200 de înregistrări.

Ceea ce este interesant (sic!) este că majoritatea Cărților de călătorie sunt, de asemenea, în tabelul Cărți, cu câteva câmpuri noi în tabelul Cărți de călătorie, în special o țară și numărul de pagini (sic din nou!). În Drupal avem o taxonomie pentru tip de carte cu lucruri de genul romantism, aventură, povești adevărate, crima, poezie etc.. precum şi Ghid turistic.

Cărți de la cărți.csv sunt deja în Drupal, cu noduri noi și termeni de taxonomie corecti aplicați domeniului field_book_type care, desigur, este un câmp cu mai multe valori.

Acum vreau să migrez cărți de călătorie.csv în Drupal dar:

  • dacă o carte există deja (căutând cu titlu, deoarece ID-urile din tabelele originale erau diferite!), trebuie doar să actualizați nodul în Drupal, adăugând termenul de taxonomie Ghid turistic
  • dacă o carte nu există în Drupal, creați-o și doar setați termenul de taxonomie Ghid turistic

Până acum am reușit să fac asta printr-un plugin Destination personalizat și nu doar cu o configurație de migrare YAML. Iată ce am sperat să folosesc:

uuid: d66124cf-232b-4080-911c-1d26aefd0246
langcode: en
stare: adevărat
dependențe: { }
id: quote_fornitore_voucher_csv_import
clasa: nula
field_plugin_method: null
cck_plugin_method: nul
migration_tags: null
migration_group: cărți
etichetă: „Importați cărți de călătorie”  
sursă:
  plugin: csv
  cale: /Users/walter/travel_books.csv
  delimitator: ','
  incintă: '"'
  header_offset: 0
  ID-uri:
    - id
  câmpuri:
    -
      nume: id
      etichetă: „Id unic”
    -
      nume: titlul_cartei
    -
      nume: tara
    -
      nume: pagini
    -
      nume: rezumat
.....
  constante:
    travel_book: „Carte de călătorie”
proces:
  tip:
    plugin: default_value
    default_value: carte
  field_pages: pagini
  field_country: country
  titlu: titlul_cartei
  field_book_type:
    plugin: entity_lookup
    entity_type: taxonomy_term
    pachet: tip_carte
    bundle_key: vid
    sursa: constants/travel_book
  nid:
    plugin: entity_generate
    tip_entitate: nod
    pachet: carte
    bundle_key: tip
    value_key: titlu
    sursa: titlul_cartei
    access_check: 0
destinaţie:
  plugin: 'entity:node' 
  overwrite_properties:
    - field_pages
    - field_country 
dependențe_migrație: nul

Am două probleme cu această migrare:

  1. Chiar dacă entity_generate găsește nodul existent corect pentru cartea curentă, motorul de migrare încă încearcă să CREEZE un nod nou, cu același NID și, desigur, eșuează cu o eroare SQL mare roșie
23000]: Încălcarea constrângerii de integritate: 1062 Dublare intrare „2662” pentru cheia „PRIMARY”: INSERT INTO „node” (“nid”, „vid”, „type”, „uuid”, „langcode”) VALUES (:db_insert_placeholder_0, :db_insert_placeholder_1, :db_insert_placeholder_2, :db_insert_placeholder_3, :db_insert_placeholder_4); Matrice
  1. Am depășit acest lucru, doar pentru a nu putea adăuga la o Carte existentă termenul de taxonomie corect la lista de field_book_type.

Am urmărit problema cu 1 pentru a fi pe care o are Entitatea enforceIsNew setată la Adevărat. Sau cel puțin asta am găsit. Am scris un plugin de destinație care, pe baza unei noi configurații, poate forța entitatea nou creată cu enforceIsNew = FALSE și se pare că funcționează conform așteptărilor. Sunt create cărți de călătorie care nu se găsesc în Cărți i nDrupal, în timp ce cele deja existente sunt actualizate, cu câmpurile pagini și țară actualizat.

Acesta este codul relevant, cred.

clasa abstractă EntityBase implementează EntityInterface {
...
  funcția publică este Nouă () {
    return !empty($this->enforceIsNew) || !$acest->id();
  }
...

Chiar dacă există un ID, care este setat de către nid proces, enforceIsNew este setat la ADEVĂRAT și așa isNew() returnează True.

<?php

spațiu de nume Drupal\migrate_books\Plugin\migrate\destination;


utilizați Drupal\Core\Entity\Entity;
utilizați Drupal\Core\Entity\EntityInterface;
utilizați Drupal\migrate\Plugin\migrate\destination\EntityContentBase;
utilizați Drupal\migrate\Plugin\MigrationInterface;
utilizați Drupal\migrate\Row;
utilizați Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * @MigrateDestination(
 * id = "nod_actualizare"
 * )
 */
clasa UpdateNodeDestination extinde EntityContentBase {

  /** @var șir $entityType */
  public static $entityType = 'nod';
 
  funcția protejată updateEntity(EntityInterface $entity, Row $row) {
    $entity = parent::updateEntity($entity, $row);
    //verificați parametrul..
    if(!empty($this->configuration['prefer_update']) && $this->configuration['prefer_update']){
      // forțați să NU aplicați NOU. Acest lucru va evita inserarea de două ori a nodurilor deja prezente (ceea ce va rezulta
      // într-o încălcare a integrității din MySQL
      $entity->enforceIsNew(FALSE);
    }
    returnează $entitate;

  }

}

iar YAMLS este schimbat cu pluginul meu și noul parametru prefer_update

destinaţie: 
  plugin: update_node
  prefer_update: adevărat
  overwrite_properties:
    - field_pages
    - field_country

dar mi se pare că ar trebui să fie mai simplu de atât. Evident că îmi lipsește ceva. Sunt sigur că acesta este un caz de utilizare destul de standard, așa că ar putea/ar trebui să fie realizabil în întregime în YAML.

În al doilea rând, încă nu pot să adaug corect tip_carte la lista etichetelor existente. Dacă adaug field_book_type la overwrite_properties, bineînțeles că este suprascris și pierdem toți termenii anteriori.

Nu mi se pare o modalitate de a actualiza prin adăugarea unei valori la un câmp cu mai multe valori.

Orice ajutor? Mulțumiri W

Postează un răspuns

Majoritatea oamenilor nu înțeleg că a pune multe întrebări deblochează învățarea și îmbunătățește legătura interpersonală. În studiile lui Alison, de exemplu, deși oamenii își puteau aminti cu exactitate câte întrebări au fost puse în conversațiile lor, ei nu au intuit legătura dintre întrebări și apreciere. În patru studii, în care participanții au fost implicați în conversații ei înșiși sau au citit transcrieri ale conversațiilor altora, oamenii au avut tendința să nu realizeze că întrebarea ar influența – sau ar fi influențat – nivelul de prietenie dintre conversatori.