I’m trying to figure out how to migrate some content into groups.

I’ll create a series of groups and remember and store an ID in a field in there. I then have a whole list of content items that I need to import into those groups (looking them up from the ID that was stored earlier) I’m just at a bit of a loss how to go about this - has anyone been down this journey already and can guide me a little or offer some advice on the way?

Comments

rachel_norfolk created an issue. See original summary.

jzavrl’s picture

I'm assuming you have some sort of .csv or something that holds your content. I personally would go about this with some custom code that would import the content and the groups. D8 has the Migration module in core but I'm not sure how it works with Groups (although we are still dealing with entities so, in theory, it should work just fine), but this can also easily be achieved.

You could also go the other way around - importing the content and then assigning that content to the group. If it exists just reference it if not the first create it. This would remove the need for storing the ID in a field.

I'm not quite sure where are you at with this, so I might be talking nonsense to you right now :)

rachel_norfolk’s picture

Thanks - got me thinking!

I have a successful migration config that imports the groups now. Pretty simple entity migration, actually. Groups working well!

Now, the second thing is, on migrate of some nodes, to assign them to the correct group as they are migrated. That's the next challenge.

When its done, I'll write this up.

rachel_norfolk’s picture

Wow - it works! Actually, turned out to be a pretty simple job of reusing the same data source (json in my case) to now create group_content entities that attach the nodes created and the groups.

So, I was migrating the nodes in with

langcode: en
status: true
dependencies: {  }
id: json_travel_story_entry
migration_tags: null
migration_group: mt_stories
label: 'JSON feed of Travel Story Entries'
source:
  plugin: url
  data_fetcher_plugin: http
  data_parser_plugin: json
  urls: 'http://path.to.json'
    uid: 1
  fields:
    -
      name: entryid
      label: 'Entry ID'
      selector: entryid
    -
      name: mt_id
      label: 'MoveableType ID'
      selector: blogid
    -
      name: title
      label: Title
      selector: title
    -
      name: date
      label: Date
      selector: date
    -
      name: body
      label: 'Body text'
      selector: body
    -
      name: excerpt
      label: 'Exceprt - sometimes empty'
      selector: excerpt
  ids:
    entryid:
      type: integer
process:
  type:
    plugin: default_value
    default_value: travel_story_update
  mt_id: mt_id
  title:
    plugin: default_value
    default_value: 'Untitled Update'
    source: title
  field_date_of_update:
    plugin: process_mt_date
    source: date
  body/value: body
  body/teaser: excerpt
  body/format:
    plugin: default_value
    default_value: rich_text
  field_entryid: entryid
  uid: constants/uid
destination:
  plugin: 'entity:node'
migration_dependencies:
  required:
    - csv_migrate_story

And then have another migration that looks at the same source:

langcode: en
status: true
dependencies: {  }
id: json_travel_story_entry_groupcontent
migration_tags: null
migration_group: mt_stories
label: 'JSON feed of Travel Story Entries - to create groupcontent'
source:
  plugin: url
  data_fetcher_plugin: http
  data_parser_plugin: json
  urls: 'http://path.to.json'
  constants:
    uid: 1
  fields:
    -
      name: entryid
      label: 'Entry ID'
      selector: entryid
    -
      name: mt_id
      label: 'MoveableType ID'
      selector: blogid
    -
      name: title
      label: Title
      selector: title
    -
      name: date
      label: Date
      selector: date
    -
      name: body
      label: 'Body text'
      selector: body
    -
      name: excerpt
      label: 'Exceprt - sometimes empty'
      selector: excerpt
  ids:
    entryid:
      type: integer
process:
  type:
    plugin: default_value
    default_value: group_content_type_040b636e0ec2b
  gid:
    plugin: migration
    migration: csv_migrate_story
    no_stub: true
    source: mt_id
  entity_id:
    plugin: migration
    migration: json_travel_story_entry
    no_stub: true
    source: entryid
  label: title
  uid: constants/uid
destination:
  plugin: 'entity:group_content'
migration_dependencies:
  required:
    - json_travel_story_entry
    - csv_migrate_story

Yes, all the data in this example is going to a single user. It’s a long story not related to the actual migration as such.

Oh - and petebarnett was a great help with providing a few pointers.

docans’s picture

Hi. I have a similar issue

I want to Migrate Nodes that are in Drupal 7 into Drupal 8 Group content. What is the best approach or migration script to achieve this

Thanks

docans’s picture

Priority: Normal » Critical
docans’s picture

I will like to importi my drupal 7 node content into a Drupal 8 Group Content that will be assigned to a group when it is imported. What is the best way to configure my YAML file for migration. Thanks

jzavrl’s picture

Without going into too much detail and investigation and writing the .yml files, I would first go into creating the group content, which is irrelevant to the nodes. Then you would probably need two migrations based on the nodes from D7. First one would be the classic one that would be migrating the nodes. The second one would be the one creating the group content entity, which would reference the previously created group entity and also the previously migrated nodes via the migration_lookup plugin.

Like I said, I haven't gone into too much investigation to tell you what should the exact mappings be, but I hope I've provided you with some guidance.

docans’s picture

@jzavrl Thanks so much for your imput.

I have been able to do the mapping and all that. My main issue now has to do with the destination plugin

I have a group type called "location". And inside the location group type i created a location called "Texas"

I will like to know how i should write my migration destination plugin to import my nodes from drupal 7 nodes into the "Texas" "group content for basic pages

The code below will get the migration into the group content

destination:
  plugin: 'entity:group_content'

But how do i specify the content to be migrated into the Texas Location Group basic page content type.

Thanks

docans’s picture

This morning i was able to get the first migration script done to import the Nodes from D7 to D8. My issue is how to now move the new nodes i brought in into group content of a specific group type using the "migration_lookup plugin" do you have any sample script i can look at.

Thanks

rachel_norfolk’s picture

Sounds like exactly what I posted above

docans’s picture

Hi Rachel.

In my case i am not using a csv to import the data. I am using the process available at https://drupalize.me/blog/201604/custom-drupal-drupal-migrations-migrate... which uses the migrate upgrade and migrate plus tool

In my Group setup, I have a group type of "States" to which i create "Texas" as one of the groups, I also have a Location content type that i have made into a Location Group Content type.

To migrate from Drupal 7 location node to Drupal location 8 node, the migration script will look like this

langcode: en
status: true
dependencies: {  }
id: upgrade_d7_node_location
class: Drupal\migrate\Plugin\Migration
field_plugin_method: null
cck_plugin_method: null
migration_tags:
  - 'Drupal 7'
migration_group: migrate_drupal_7
label: 'Nodes (Location)'
source:
  plugin: d7_node
  node_type: location
process:
  nid: tnid
  vid: vid
  langcode:
    plugin: default_value
    source: language
    default_value: und
  title: title
  uid: node_uid
  field_poc_email:
    plugin: iterator
    source: field_location_email
    process:
      value: email
  field_poc_phone: field_location_phone
destination:
  plugin: 'entity:node'
  default_bundle: location
migration_dependencies:
  required:
    - upgrade_d7_user
    - upgrade_d7_node_type

However to migrate from Drupal 7 location node to Drupal 8 "Location Group content type node" for the "Texas" Group ,i want to know how to modify the destination parameters. I know it will look something like

destination:
  plugin: 'entity:group_content'

What should i add to the destination plugin to direct the nodes being migrated to the ( Location Group content type ) for the ( Texas Group). and where would i use the "migration_lookup plugin" to achieve this

I hope this clarifies it better. Any help is appreciated.

docans’s picture

I have a few errors i want to share

when i run my migration script below

langcode: en
status: true
dependencies: {  }
id: upgrade_d7_node_location
class: Drupal\migrate\Plugin\Migration
field_plugin_method: null
cck_plugin_method: null
migration_tags:
  - 'Drupal 7'
migration_group: migrate_drupal_7
label: 'Nodes (Location)'
source:
  plugin: d7_node
  node_type: location
process:
  nid: tnid
  vid: vid
  langcode:
    plugin: default_value
    source: language
    default_value: und
  title: title
  uid: node_uid
  field_poc_email:
    plugin: iterator
    source: field_location_email
    process:
      value: email
  field_poc_phone: field_location_phone
destination:
  plugin: 'entity:group_content'

This is the error i got , is there anything missing that i did not do right

{ docroot } drush migrate-import                                                                                                       
Error: Call to a member function getContentPlugin() on null in Drupal\group\Entity\GroupContent->getContentPlugin() (line 102 of                                                  
/var/www/docroot/modules/contrib/group/src/Entity/GroupContent.php) #0 /var/www/docroot/modules/contrib/group/src/Entity/GroupContent.php(127):
Drupal\group\Entity\GroupContent->getContentPlugin()
#1 /var/www/docroot/modules/contrib/group/src/Entity/GroupContent.php(190): Drupal\group\Entity\GroupContent->label()
#2 /var/www/docroot/core/lib/Drupal/Core/Entity/EntityStorageBase.php(434): Drupal\group\Entity\GroupContent->preSave(Object(Drupal\group\Entity\Storage\GroupContentStorage))
#3 /var/www/docroot/core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php(292): Drupal\Core\Entity\EntityStorageBase->doPreSave(Object(Drupal\group\Entity\GroupContent))
#4 /var/www/docroot/core/lib/Drupal/Core/Entity/EntityStorageBase.php(389): Drupal\Core\Entity\ContentEntityStorageBase->doPreSave(Object(Drupal\group\Entity\GroupContent))
#5 /var/www/docroot/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php(796): Drupal\Core\Entity\EntityStorageBase->save(Object(Drupal\group\Entity\GroupContent))
#6 /var/www/docroot/core/lib/Drupal/Core/Entity/Entity.php(377): Drupal\Core\Entity\Sql\SqlContentEntityStorage->save(Object(Drupal\group\Entity\GroupContent))
#7 /var/www/docroot/core/modules/migrate/src/Plugin/migrate/destination/EntityContentBase.php(109): Drupal\Core\Entity\Entity->save()
#8 /var/www/docroot/core/modules/migrate/src/Plugin/migrate/destination/EntityContentBase.php(90):
Drupal\migrate\Plugin\migrate\destination\EntityContentBase->save(Object(Drupal\group\Entity\GroupContent), Array)
#9 /var/www/docroot/core/modules/migrate/src/MigrateExecutable.php(224): Drupal\migrate\Plugin\migrate\destination\EntityContentBase->import(Object(Drupal\migrate\Row), Array)
#10 phar:///usr/local/bin/drush/includes/drush.inc(720): Drupal\migrate\MigrateExecutable->import()
#11 phar:///usr/local/bin/drush/includes/drush.inc(711): drush_call_user_func_array(Array, Array)
#12 /var/www/docroot/modules/contrib/migrate_tools/migrate_tools.drush.inc(282): drush_op(Array)
#13 [internal function]: _drush_migrate_tools_execute_migration(Object(Drupal\migrate\Plugin\Migration), 'upgrade_d7_node_location', Array)
#14 /var/www/docroot/modules/contrib/migrate_tools/migrate_tools.drush.inc(248): array_walk(Array, '_drush_migrate_...', Array)
#15 phar:///usr/local/bin/drush/includes/command.inc(422): drush_migrate_tools_migrate_import('upgrade_d7_node_location')
#16 phar:///usr/local/bin/drush/includes/command.inc(231): _drush_invoke_hooks(Array, Array)
#17 phar:///usr/local/bin/drush/includes/command.inc(199): drush_command('upgrade_d7_node_location')
#18 phar:///usr/local/bin/drush/lib/Drush/Boot/BaseBoot.php(67): drush_dispatch(Array)
#19 phar:///usr/local/bin/drush/includes/preflight.inc(66): Drush\Boot\BaseBoot->bootstrap_and_dispatch()
#20 phar:///usr/local/bin/drush/includes/startup.inc(458): drush_main()
#21 phar:///usr/local/bin/drush/includes/startup.inc(365): drush_run_main(false, '/', 'Phar detected. ...')
#22 phar:///usr/local/bin/drush/drush(114): drush_startup(Array)
#23 /usr/local/bin/drush(10): require('phar:///usr/loc...')
#24 {main}.
[01-Nov-2017 21:19:56 UTC] Error: Call to a member function getContentPlugin() on null in /var/www/docroot/modules/contrib/group/src/Entity/GroupContent.php on line 102 #0 /var/www/docroot/
modules/contrib/group/src/Entity/GroupContent.php(127): Drupal\group\Entity\GroupContent->getContentPlugin()
#1 /var/www/docroot/modules/contrib/group/src/Entity/GroupContent.php(190): Drupal\group\Entity\GroupContent->label()
#2 /var/www/docroot/core/lib/Drupal/Core/Entity/EntityStorageBase.php(434): Drupal\group\Entity\GroupContent->preSave(Object(Drupal\group\Entity\Storage\GroupContentStorage))
#3 /var/www/docroot/core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php(292): Drupal\Core\Entity\EntityStorageBase->doPreSave(Object(Drupal\group\Entity\GroupContent))
#4 /var/www/docroot/core/lib/Drupal/Core/Entity/EntityStorageBase.php(389): Drupal\Core\Entity\ContentEntityStorageBase->doPreSave(Object(Drupal\group\Entity\GroupContent))
#5 /var/www/docroot/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php(796): Drupal\Core\Entity\EntityStorageBase->save(Object(Drupal\group\Entity\GroupContent))
#6 /var/www/docroot/core/lib/Drupal/Core/Entity/Entity.php(377): Drupal\Core\Entity\Sql\SqlContentEntityStorage->save(Object(Drupal\group\Entity\GroupContent))
#7 /var/www/docroot/core/modules/migrate/src/Plugin/migrate/destination/EntityContentBase.php(109): Drupal\Core\Entity\Entity->save()
#8 /var/www/docroot/core/modules/migrate/src/Plugin/migrate/destination/EntityContentBase.php(90): Drupal\migrate\Plugin\migrate\destination\EntityContentBase->save(Object(Drupal\group\Enti
ty\GroupContent), Array)
#9 /var/www/docroot/core/modules/migrate/src/MigrateExecutable.php(224): Drupal\migrate\Plugin\migrate\destination\EntityContentBase->import(Object(Drupal\migrate\Row), Array)
#10 phar:///usr/local/bin/drush/includes/drush.inc(720): Drupal\migrate\MigrateExecutable->import()
#11 phar:///usr/local/bin/drush/includes/drush.inc(711): drush_call_user_func_array(Array, Array)
#12 /var/www/docroot/modules/contrib/migrate_tools/migrate_tools.drush.inc(282): drush_op(Array)
#13 [internal function]: _drush_migrate_tools_execute_migration(Object(Drupal\migrate\Plugin\Migration), 'upgrade_d7_node_location', Array)
#14 /var/www/docroot/modules/contrib/migrate_tools/migrate_tools.drush.inc(248): array_walk(Array, '_drush_migrate_...', Array)
#15 phar:///usr/local/bin/drush/includes/command.inc(422): drush_migrate_tools_migrate_import('upgrade_d7_node_location')
#16 phar:///usr/local/bin/drush/includes/command.inc(231): _drush_invoke_hooks(Array, Array)
#17 phar:///usr/local/bin/drush/includes/command.inc(199): drush_command('upgrade_d7_node_location')
#18 phar:///usr/local/bin/drush/lib/Drush/Boot/BaseBoot.php(67): drush_dispatch(Array)
#19 phar:///usr/local/bin/drush/includes/preflight.inc(66): Drush\Boot\BaseBoot->bootstrap_and_dispatch()
#20 phar:///usr/local/bin/drush/includes/startup.inc(458): drush_main()
#21 phar:///usr/local/bin/drush/includes/startup.inc(365): drush_run_main(false, '/', 'Phar detected. ...')
#22 phar:///usr/local/bin/drush/drush(114): drush_startup(Array)
#23 /usr/local/bin/drush(10): require('phar:///usr/loc...')
#24 {main}
Error: Call to a member function getContentPlugin() on null in Drupal\group\Entity\GroupContent->getContentPlugin() (line 102 of /var/www/docroot/modules/contrib/group/src/Entity/GroupConte
nt.php).
Drush command terminated abnormally due to an unrecoverable error.  
docans’s picture

Hi Guys. Can anyone please point me in the right direction please

nxmassa’s picture

So this doesn't solve the exact problem as it's written in the issue, but we were able to use this method to achieve our goal of getting content into a group after the migration. As detailed in this issue: https://www.drupal.org/node/2772623 the Groups module has a function called addContent() which relates nodes to groups. In a helper module, I added that function to a hook_node_insert() as follows:

function hook_node_insert($node) {
  // Load whole entity
  $entity = \Drupal::entityTypeManager()->getStorage("node")->load($node->id());

  // Load group and add $entity to group
  $group = \Drupal::entityTypeManager()->getStorage('group')->load($group_id);
  $group->addContent($entity, 'group_node:article');
}

With this in place we ran our migration and the nodes ended up in the correct groups.

It didn't work perfectly and it's not a great solution to this specific problem, but it helped us achieve our goals in the meantime.

deepak_123’s picture

Thank you @rachel_norfolk for #4. This saved my life :)

Here is are the two yamls i used for migrating the nodes with the first yaml, then associating them to the group with the second yaml.

For migrating nodes -

uuid: c37b18e0-a3ff-4345-8fd5-04a63e1de8b3
langcode: en
status: true
dependencies: {  }
id: community_question_node_migration
class: null
field_plugin_method: null
cck_plugin_method: null
migration_tags:
  - 'Community Question node migration'
migration_group: insert_group
label: 'Migrate Community Questions nodes to D8'
source:
  plugin: csv
  path: 'public://csv/community_question_migration.csv'
  header_row_count: 1
  keys:
    - nid
  column_names:
    -
      nid: 'The D7 node id'
    -
      title: 'The node title'
    -
      path: 'The aliased path'
    -
      branched_post_information: 'The Branched Post Information field'
    -
      body: 'The body field'
    -
      product_topic_category: 'The Product Topic Category field'
    -
      send_update_notifications: 'The Send update notifications field'
    -
      question_id: 'The Question Id field'
    -
      mark_this_as_a_question: 'The Mark this as a question field'
    -
      groups_audience: 'The Groups audience field'
    -
      correct_cid: 'The Correct cid field'
    -
      assumed_answered: 'Assumed Answered field'
    -
      file_attachments: 'File attachments field'
    -
      og_vocabulary: 'OG vocabulary field'
    -
      search_results_visibility: 'Search results visibility field'
    -
      archive: 'Archive field'
    -
      tags: 'The Tags field'
    -
      forum: 'The Forum field'
    -
      related_support_case_number: 'The Related Support Case Number field'
    -
      last_commented_date: 'The Last commented date field'
    -
      suspicious_content: 'The Suspicious content field'
    -
      approved_by: 'The Approved By field'
    -
      created_on: 'Created on'
    -
      updated_date: 'Updated Date'
    -
      author_name: Author
    -
      author_uid: 'Author uid'
    -
      published: 'Is the node published?'
    -
      version_id: 'Version ID'
    -
      revision_uid: 'Revision author uid'
    -
      revision_log: 'The moderation log'
    -
      revision_timestamp: 'Revision Timestamp'
process:
  type:
    plugin: default_value
    default_value: community_question
  langcode:
    plugin: default_value
    source: language
    default_value: und
  title: title
  field_branched_post/value: branched_post_information
  field_branched_post/format:
    plugin: default_value
    default_value: rich_text
  body/value: body
  body/format:
    plugin: default_value
    default_value: rich_text
  field_og_group_ref: groups_audience
  uid:
    plugin: migration_lookup
    migration: user
    source: author_uid
    no_stub: true
  path/pathauto:
    plugin: default_value
    default_value: 0
  path: path
  status: published
  field_d7_node_id: nid
  revision_log: revision_log
destination:
  plugin: 'entity:node'
migration_dependencies:
  required:
    - author_uid

Then second migration for associating nodes to the groups -

uuid: 9fdce8e0-93e2-44b0-8a4f-fd56c51aa458
langcode: en
status: true
dependencies: {  }
id: community_question_groupcontent_migration
class: null
field_plugin_method: null
cck_plugin_method: null
migration_tags:
  - 'Community Question group content migration'
migration_group: insert_group
label: 'Migrate Community Questions group content to Group'
source:
  plugin: csv
  path: 'public://csv/community_question_migration.csv'
  header_row_count: 1
  keys:
    - nid
  column_names:
    -
      nid: 'The D7 node id'
    -
      title: 'The node title'
    -
      path: 'The aliased path'
    -
      branched_post_information: 'The Branched Post Information field'
    -
      body: 'The body field'
    -
      product_topic_category: 'The Product Topic Category field'
    -
      send_update_notifications: 'The Send update notifications field'
    -
      question_id: 'The Question Id field'
    -
      mark_this_as_a_question: 'The Mark this as a question field'
    -
      groups_audience: 'The Groups audience field'
    -
      correct_cid: 'The Correct cid field'
    -
      assumed_answered: 'Assumed Answered field'
    -
      file_attachments: 'File attachments field'
    -
      og_vocabulary: 'OG vocabulary field'
    -
      search_results_visibility: 'Search results visibility field'
    -
      archive: 'Archive field'
    -
      tags: 'The Tags field'
    -
      forum: 'The Forum field'
    -
      related_support_case_number: 'The Related Support Case Number field'
    -
      last_commented_date: 'The Last commented date field'
    -
      suspicious_content: 'The Suspicious content field'
    -
      approved_by: 'The Approved By field'
    -
      created_on: 'Created on'
    -
      updated_date: 'Updated Date'
    -
      author_name: Author
    -
      author_uid: 'Author uid'
    -
      published: 'Is the node published?'
    -
      version_id: 'Version ID'
    -
      revision_uid: 'Revision author uid'
    -
      revision_log: 'The moderation log'
    -
      revision_timestamp: 'Revision Timestamp'
process:
  type:
    plugin: default_value
    default_value: group_content_type_c09d09f4991ab
  langcode:
    plugin: default_value
    source: language
    default_value: und
  gid:
    plugin: migration_lookup
    migration: community_migration
    no_stub: true
    source: groups_audience
  entity_id:
    plugin: migration_lookup
    migration: community_question_node_migration
    no_stub: true
    source: nid
  label: title
  uid:
    plugin: migration_lookup
    migration: user
    source: author_uid
    no_stub: true
destination:
  plugin: 'entity:group_content'
migration_dependencies:
  required:
    - groups_audience
    - author_uid
    - nid
rachel_norfolk’s picture

Yay! Glad it worked for you

taylormade415’s picture

@deepak_123 / @rachel_norfolk , where did you get the default group_content_type_c09d09f4991ab value? i've devel'd around the group_content and most variations of the machine names are more group groups-group_membership, or other combinations.

dokumori’s picture

@taylormade415 I assume you've already figured it out, but for those who are wondering how/where to find it:

It's in the DB - after adding some content to a group (in my case, I added group membership), see the content of the table `group_content`. Under the `type` field, you will see strings like `group_content_type_c09d09f4991ab`

moshe weitzman’s picture

Priority: Critical » Major

This was helpful to me as well. The re-saving that we do is super not performant in a migration scenario where you do so many entity saves.

moshe weitzman’s picture

Here is a patch that might be useful for folks who are migrating. If your process pipeline sets $entity->migrate = TRUE, then this patch will skip the resaving of groupContent during save and delete operations. That re-save is super slow. At end of all migrations, I suggest rebuilding node permissions. I *think* thats sufficient.

moshe weitzman’s picture

Sorry, this one avoids a warning.

zcht’s picture

has someone here migrated group 1.0 with the new subgroup module by chance? the structure of the subgroups has changed a bit, a new process plugin is needed now. now i am looking for a solution, maybe someone has already done something in that direction?

maebug’s picture

The format of the value to use for the `type` field has changed since @dokumori's comment. It is now in the format [group_type_id]-[plugin_id]. For example, I have a group type that has an ID of `calendar` with the group content plugin for `event` nodes enabled. So my default value is `calendar-group_node-event`.

The process for figuring this out is the same: create example content and look at the `type` column of the `group_content` table in your database.

Example:

process:
  type:
    plugin: default_value
    default_value: calendar-group_node-event
megha_kundar’s picture

But this doesn't work with 3.x version of group
Can anyone guide me in migrating groups module
Please ?

megha_kundar’s picture

Version: 8.x-1.0-beta2 » 3.0.0-rc2
mcortes19’s picture

In group v3 the group_content was changed to group_relationship, also it requires the plugin_id field, so your migration could look like this:

source:
  plugin: d7_node
  node_type: oportunity
process:
  type:
    plugin: default_value
    default_value: program-group_node-opportunity
  plugin_id:
    plugin: default_value
    default_value: group_node:opportunity
  gid:
    plugin: migration_lookup
    migration: groups_audience
    no_stub: true
    source: groups_audience
  entity_id:
    plugin: migration_lookup
    migration: program_node_migration
    no_stub: true
    source: nid
destination:
  plugin: 'entity:group_relationship'