Development

Migrating Into Existing Nodes in Drupal 8, Including Rollback Missing from Source

Please read this entire post (including the disclaimer at the bottom) before you put any of it to use.

The site I’m basing this off had an existing set of nodes and a new migration that had the same nodes (and many more) in the data source. I wanted to map the existing nodes to their migration-based counterparts and treat every node as if it originated from the migration.

As of today, using a few patches makes it easy (thanks contributors!) to rollback items that no longer exist in a D8 migration’s source data. See Migrate support for deleting items no longer in the incoming data and Implement rollback of items no longer in source data

With these patches you can import and rollback in two commands:

What if the data that you’re migrating (and rolling back if removed) already existed in Drupal before you started using the migration? If you attempt to migrate content, then rollback removed items, you will find that the items that no longer exist in the source will not be deleted if they existed before the migration.

First, I should describe how I’m pulling data into existing nodes.

This is as simple as populating the node ID in the process section of your migration YML, like this:

In my case I’m looking up the existing_nid value in a custom source plugin. It looks something like this:

With the nid mapping set up you can import on top of existing nodes.

What about rolling back items that were deleted from the source data?

Here’s the method from core that drives, in the migrate map tables, whether or not a record will be deleted, or preserved, on rollback:

Notice that when we are “updating an entity which already existed on the destination…” we preserve instead of delete.

This explains why the nodes that no longer exist in the source will not be deleted if they existed before the migration. The only thing that is deleted is the row in the migrate map table (as far as I can tell).

In my case, after I run the initial migration in production, all of the data will be mapped. I do not wish to preserve anything that wasn’t in the source data when I run the initial migration. So, my solution will be to run a query in production (after taking a database backup) that will simply set all of these nodes to a rollback_action of 0 (delete) instead of 1 (preserve) in the migrate map table. I don’t have any other migrations at the moment, so it’s as easy as:

I realize things could be more complicated for you. I just figured I’d share what I’ve learned in hopes that it’ll help someone get a little bit further in their own site.

UPDATE / DISCLAIMER:

If you specify which fields should be overwritten by the source data (shown below) the setRollbackAction() method will always set the update action back to 1.

 

One Comment

Leave a Reply

Your email address will not be published.