I am migrating from a another non Drupal CMS. I have 4 tables:

  • stories (story1, story2, story3)
  • story_tags (story_id, tag_id)
  • tags (ABC, NBC, WTOP, CBS, clinton)
  • tag_types (radio, tv, person)

How can I link tags to stories by tag_type. So that when I open a story I can see all it's related tags, knowing that a story can have several tags.
Any good detailed tutorial of migrate module link will be appreciated also.

How can i translate this in a migrate query

SELECT t.name FROM tags t 
    join tag_types tt on (tt.id = 3)
    join story_tags stg on (stg.tag_id = t.id) WHERE story_id = $row_id'   

Tried but it is not working:

->select('story_tags', 'tags')
->fields('tags', array('tag_id'))
->leftJoin('tag_types', 'tt', '(tt.id = tag.tag_type_id)')
->condition('tag_type_id', '3', '=' )
->condition('story_id', $row->id, '=')

What am i missing?

1 Answer 1


My approach to this would be to have a content type called Story that had 2 taxonomy term references. One tag field could just be called tags and then other could be called tag_types. These 2 fields would be 2 distinct Taxonomy Vocabularies in Drupal.

Drupal 7 actually installs with a tags vocabulary out-of-the-box which is assumed to be free-tagging terms as your legacy site appears to be already using. So you just need to make 1 vocabulary for the tag_types.

Anyways then in your migration class for Stories. Your source SQL statement would figure out the necessary terms for these 2 fields, probably using a sub-select, and the migrate module can set the terms for the content type as Stories are inserted into the system.

So, some psuedocode is:


class StoryMigration extends Migration
  public function __construct($arguments)
    $query = Database::getConnection('default', 'legacy')
      ->fields('stories', array('pgid', 'page_title', 'page_body'));
    // Create subqueries to get the tags for the story we are on. We will call
    // a fake field in our SQL query as legacy_tags or legacy_tags_type to be
    // passed using Migrate field mappings.
    $query->addExpression('SELECT GROUP_CONCAT(term_name) FROM legacydb_terms WHERE page_id = pgid' ,'legacy_tags');
    $query->addExpression('SELECT GROUP_CONCAT(term_name) FROM legacydb_term_types WHERE page_id = pgid' ,'legacy_tags_type');
    $this->source = new MigrateSourceSQL($query);
    $this->destination = new MigrateDestinationNode('page');

    $this->map = new MigrateSQLMap($this->machineName,
        'pgid' => array('type' => 'int',
          'unsigned' => TRUE,
          'not null' => TRUE,
          'description' => t('Source ID'),

    $this->addFieldMapping('title', 'page_title');
    $this->addFieldMapping('body', 'page_body');

    // Import a story's tag(s). Make the term in the vocabulary if it's not
    // there already, ignore the CaSe of the term so sloppy legacy terms
    // come across as 1 term.
    // By specifying this could have a SEPERATOR VALUE this can create any N
    // terms provided by our SQL statement above.
    $this->addFieldMapping('field_tags', 'legacy_tags');

    // Similar steps as for the above term, but for the tags_type reference field.
    $this->addFieldMapping('field_tags_type', 'legacy_tags_type');

Term Reference Fields and the Migrate module are described in the documentation. Adding SQL Expressions to an SQL query is covered in the sql documentation.

My above code is an example and not guarenteed to work. It's simply 1 method of doing this and is to be referenced as an outline. Your SQL schema and php may look different in the end.

  • Thanks, I added an update. Do you know how to fix the query?
    – mamesaye
    Commented Jan 25, 2016 at 3:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.