I am currently working on a module to migrate a site's users and articles from D6 to D7.

Following the examples I have been successful with the Article migration right up to the body of the node. I've JOINed the D6 'node_revisions' table and have extracted both "body" and "teaser" from there:

  $query->join(D6_DATABASE.'.node_revisions', 'nr', 'n.vid = nr.vid');
  $query->addField('nr', 'body');
  $query->addField('nr', 'teaser');

Then the field mapping
$this->addFieldMapping('body', 'body');
correctly INSERTs the "body" value into the 'field_data_body.body_value' field in the D7 database. So it seems to me that the Migrate class (or at least the member function addFieldMapping()) clearly knows that 'body' actually means 'field_data_body.body_value' in the back-end.

How do I get the D6 'node_revisions.teaser' value into D7 'field_data_body.body_summary'?

Comments

nerdcore’s picture

This works, but I am curious if there is a cleaner way to accomplish this:

public function complete($node, $r) {
  $teaser_insert = db_update('field_data_body')
    ->fields(array('body_summary' => $r->teaser))
    ->condition('entity_id', $node->nid, '=')
    ->execute();
}
mikeryan’s picture

Status: Active » Fixed

This is much simpler:

    $arguments = MigrateTextFieldHandler::arguments(array('source_field' => 'teaser'));
    $this->addFieldMapping('body', 'body')
         ->arguments($arguments);

This technique is covered in the migrate_example module bundled with migrate - see BeerNodeMigration in beer.inc.

nerdcore’s picture

Status: Fixed » Active

How about a node's taxonomy? I'm having a lot of trouble getting terms, which were migrated using Migrate and have their own map table, from D6 into D7.

Examples of field mappings has an example of imploded values:

    $this->addFieldMapping('field_country', 'countries')
     ->separator(',');

And this is in reference to taxonomy terms, but I am unsure of how to load my terms from D6 into an imploded text string for use in this fashion. I thought this would work:

public function __construct() {
  // ...
    $this->addFieldMapping('field_region', 'region')
      ->separator(',');
}

public function prepareRow($row) {
  $terms_query = db_select(OLD_DATABASE.'.term_node', 'tn')
    ->fields('tn', array('tid'))
    ->condition('tn.vid', $row->vid, '=');
  $terms_query->join('migrate_map_myterm', 'term_map', 'tn.tid = term_map.sourceid1');
  $terms_query->addField('term_map','destid1','newtid');
  $terms_query->join('taxonomy_term_data', 'ttd', 'ttd.tid = term_map.destid1');
  $terms_query->addField('ttd', 'vid');
  $res = $terms_query->execute();

  $tids = array();
  while($record = $res->fetchAssoc())
    array_push($tids, $record['newtid']);

  $row->region = join(',', $tids);

But that doesn't work. prepareRow() is definitely getting the correct info and creating the array as expected, but the field mapping simply doesn't happen (adding the field "region" to the stdClass "$row" doesn't seem to make it available for mapping in the constructor.

Also, the suggestion made on the Examples of field mappings page, as well as the WineMigration example are both specifying which vocabulary to use for terms. Is there a way this could be generalized so that terms of ANY vocabulary are mapped into the correct fields at the destination? I've edited my D7 content type to include fields for the four necessary vocabularies ("region" is one), but in writing a Migration I would like to make the code as general as possible for future re-use, so can we pull vocabulary machine_names from the DB instead of specifying? Ideally something very general like:

foreach ($terms_for_node as $term) {
  $this->addFieldMapping('field_'.$term->vocabulary_machine_name, $term->vocabulary_machine_name);
}
nerdcore’s picture

The BeerNodeMigration uses the following:

    $query->leftJoin('migrate_example_beer_topic_node', 'tb', 'b.bid = tb.bid');
    // Gives a single comma-separated list of related terms
    $query->groupBy('tb.bid');
    $query->addExpression('GROUP_CONCAT(tb.style)', 'terms');
    // ...
    // These are related terms, which by default will be looked up by name
    $this->addFieldMapping('migrate_example_beer_styles', 'terms')
         ->separator(',');

So I had hoped I could use this to migrate terms of vocabulary "Region" into a 'field_region' field on D7:

    $query->leftJoin(OLD_DATABASE.'.term_node', 'tn', 'n.vid = tn.vid');
    $query->groupBy('tn.vid');
    $query->addExpression('GROUP_CONCAT(tn.tid)', 'terms');
    // ...
    $this->addFieldMapping('field_region', 'terms')
      ->separator(',');

The above code results in an empty field_region array on the imported node, instead of the region assigned to it on the D6 side.

nerdcore’s picture

This is totally ugly but it works:

  // __construct() has field mapping for these in the form
  // $this->addFieldMapping('field_region', 'region')->separator(',');

  public function prepareRow($row) {
    $terms_select = db_select(OLD_DATABASE.'.term_data', 'td')
      ->fields('td', array('vid', 'name'));
    $terms_select->join(OLD_DATABASE.'.term_node', 'tn', 'td.tid = tn.tid');
    $terms_select->condition('tn.vid', $row->vid, '=');

    $terms_result = $terms_select->execute();

    $regions = array();
    $audiences = array();
    $aois = array();
    $rscs = array();
    foreach($terms_result as $res) {
      switch ($res->vid) { // These are the appropriate Vocabulary IDs from D6
      case '1':
        $regions[] = $res->name;
        break;
      case '2':
        $audiences[] = $res->name;
        break;
      case '3':
        $aois[] = $res->name;
        break;
      case '4':
        $rscs[] = $res->name;
        break;
      }
      $row->region = join(',', $regions);
      $row->audience = join(',', $audiences);
      $row->area_of_interest = join(',', $aois);
      $row->rsc = join(',', $rscs);
    }
  }
mikeryan’s picture

Status: Active » Fixed

Not that ugly (particularly if you remove the join() calls at the end, leaving them as arrays is just fine), that's the usual method for getting multiple-value related data into the source row.

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.