What is the proper way to migrate field collections that contain multiple items? I've successfully migrated one field collection item per collection (following this example: https://www.drupal.org/node/2721823#comment-11225251), but haven't found a way to import multiple items to the same collection.
I've tried the migration a few different ways:
Method 1: Passing arrays of field data into the field collection field destinations
As described here: https://www.drupal.org/node/2129651#handling_multiple
Sample migration query result:
Array
(
[0] => stdClass Object
(
[nid] => 389
[fee_values] => Array
(
[0] => 10
[1] => 15
[2] => 25
)
[fee_labels] => Array
(
[0] => Childen
[1] => Seniors
[2] => Adults
)
)
[1] => stdClass Object
(
[nid] => 405
[fee_values] => Array
(
[0] => 30
[1] => 45
)
[fee_labels] => Array
(
[0] => Early Registration
[1] => Day-Of
)
)
)
Migration config:
process:
field_name:
plugin: default_value
default_value: field_event_fees
host_type:
plugin: default_value
default_value: node
host_entity_id:
plugin: migration
migration: event_node
source: nid
field_cost: fee_values
field_fee_name: fee_labels
Result: First field collection item appears in the Node edit page, but not subsequent items.
Method 2: Each Field Collection Item as a separate row
Sample migration query result:
[0] => stdClass Object
(
[nid] => 389
[field_fee_value] => 10
[field_fee_label_value] => Children
[id] => 389_1
)
[1] => stdClass Object
(
[nid] => 389
[field_fee_value] => 15
[field_fee_label_value] => Seniors
[id] => 389_2
)
[2] => stdClass Object
(
[nid] => 389
[field_fee_value] => 25
[field_fee_label_value] => Adults
[id] => 389_3
)
[3] => stdClass Object
(
[nid] => 405
[field_fee_value] => 30
[field_fee_label_value] => Early Registration
[id] => 405_1
)
[4] => stdClass Object
(
[nid] => 405
[field_fee_value] => 45
[field_fee_label_value] => Day-Of
[id] => 405_2
)
Migration config:
process:
field_name:
plugin: default_value
default_value: field_event_fees
host_type:
plugin: default_value
default_value: node
host_entity_id:
plugin: migration
migration: event_node
source: nid
field_cost: field_fee_value
field_fee_name: field_fee_label_value
Result: First field collection item appears in the Node edit page, but not subsequent items.
I've also tried the iterator plugin but it didn't seem to suit the use case.
So, is there another approach that I should be using?
Comment | File | Size | Author |
---|---|---|---|
#15 | 2757989-migrate-multi-value-field-collection-15.patch | 5.29 KB | jmoreira |
| |||
#14 | 2757989-migrate-multi-value-field-collection-14.patch | 3.43 KB | jmoreira |
| |||
#7 | 2757989-patch-migrate-multi-value-field-collection.diff | 3.13 KB | heshanlk |
|
Comments
Comment #2
jmuzz CreditAttribution: jmuzz commented8.x-2.x is no longer being developed or supported.
Comment #3
willcode4food CreditAttribution: willcode4food commentedHello,
While this issue is closed, I am running into the same problem. What is the appropriate way to continue communication regarding this issue in the supported version?
Thank you.
Comment #4
mikeker CreditAttribution: mikeker as a volunteer commentedThis issue transcends versions.
Comment #5
mikeker CreditAttribution: mikeker as a volunteer commentedI've been banging my head against this for the last couple days... The fundamental problem is that the destination plugin (
entity:field_collection_item
) only creates a single field collection item. Based on that it would be ideal to use something like the iterator process plugin to go through a multi-value field and create one item per incoming value. But I haven't been able to get the iterator plugin to, well, iterate correctly... (Though that's more likely because of my lack of understanding in the Migrate API!)Another option is to update the destination plugin to be aware of multi-value fields and create new field collection items. But that breaks things farther down the road (eg: the migrate_map table expects a single source ID to map to a single destination ID).
Just some thoughts -- I'll post again if I make any headway.
Comment #6
mikeker CreditAttribution: mikeker as a volunteer commentedOK, I think I've finally cracked this... What I've learned:
My scenario: Drupal 6 content type with two multi-value fields (
field_dsm_version
andfield_dsm_body
) that were tied together via Content Multigroup that needed to migrate to a D8 content type using Field Collection to tie the fields together.I ran it as two migrations: one to move all the non-field-collection fields into D8 and a second to build the field collections and the reference in the node built in step one. First migration is straightforward. I wrote a custom source plugin for the second migration to allow multiple field collection references. The key was to define
getIds()
to return both the source node ID and the field delta as keys. That way the Migrate API sees number_of_nodes * number_of_deltas as the total number needed to import.Migration YAML file:
Source plugin (some code removed for brevity and privacy):
Comment #7
heshanlkExample YML code to use with this patch.
Comment #8
dremy CreditAttribution: dremy commentedI was banging my head against this for awhile but it appears that I finally have it working.
Here's my YML, no patch necessary. Hopefully this helps someone else.
Comment #9
mikeker CreditAttribution: mikeker as a volunteer commented@dremy: In the CSV file, was there a one-row-to-one-field-collection-item mapping? Or was it one row to multiple field collection items?
Thanks!
Comment #10
dremy CreditAttribution: dremy commented@mikeker it was one row to one field collection item, although the host entity could have multiple field collection items on it.
Comment #11
jmoreira CreditAttribution: jmoreira as a volunteer commentedUse case: migrate field collections from a multilingual D7 site to paragraphs a multilingual D8 site.
Note: In this scenario, the Content Translation module is being used for D7, so each translation is an individual node.
Solution: I had to alter the patch on #7 to get the revision id from the field data table instead of the field collection item or else the revision mapping would get messed up because in some cases the revision on the field collection item table is different from the one sent by the field when migrating the parent node. Also, because each field collection item is related to a single node and Paragraphs don't accept field translation(https://www.drupal.org/node/2735121) the only quick solution I found was to migrate each translation as individual nodes. A better solution, I think, would be to add another JOIN in the query by node and use the node's tnid and the field's delta to "merge" all field collections and their object into one translatable object and add individual translations by field, kind of similar to what was done at: https://www.drupal.org/node/2669964 . That should take some time and testing, though.
Here are the yml files of my solution for reference:
File: migrate_plus.migration.field_collection_field_name.yml
File: migrate_plus.migration.node_node_type.yml
Comment #13
jmoreira CreditAttribution: jmoreira as a volunteer commentedComment #14
jmoreira CreditAttribution: jmoreira as a volunteer commentedFixing patch from #11.
Comment #15
jmoreira CreditAttribution: jmoreira as a volunteer commentedNot sure if this is the best(or a good) solution, but here's what I've done to make it work:
After apply the patch, you need to add a source property translations: true to the field collection item migration and in the host node migration you'll need to use the d7_node_fci source and specify the specify the migrate field collection fields in the source property: field_collection_fields. Something like:
As soon as I have sometime I'll post a full example of this working.
Comment #16
dhruva2 CreditAttribution: dhruva2 commentedGuys what you meant with the multivalue field-collection.
Comment #17
rovoCross linking to the issue in the Paragraphs module, since that is the likely replacement in D8.
Comment #18
jmoreira CreditAttribution: jmoreira as a volunteer commentedComment #19
ram4nd CreditAttribution: ram4nd as a volunteer commented