How do I collect ids from a set of multi-references fields in one item from one collection, and use it to overwrite the multi-reference fields for another item in another collection?

Question:
How do I successfully take values in an item’s multi-reference fields in one collection, map it to another item’s multireference fields in another collection, and then update the fields in the item in the second collection with the values from the item in the first collection?

Product:
Wix Website Editor

What are you trying to achieve:
I have two collections. A draft collection I use to check items, and confirm edits, and a published collection tied to the elements/dynamic pages on my website. I am trying to write an after update/after insert data hook that says when certain conditions are met in the draft collection, the details for the item in the draft collection, including its references, overwrite the item in the published collection.

What have you already tried:
The way I originally planned to do this was:
(1) Use a unique Id that connects the item in the draft and published collections. This id is used to find the corresponding item in the official collection.
(2) Pull the references from the multi-reference values for the item in the draft collection.
(3) Map the multi-reference fields from the draft collection to the multi-reference fields for the published collection.
(4) If the draft item is found in the published collection, update the published collection with the information from the draft collection, and then update the references using the map. If the item is not found in the published collection, insert the information from the draft item as a new item in the published collection, and insert the references as well.

Here is the code I have so far:

async function UpdateCollection () {

// if (item.logoStatus === “Logo Approved” && item.reviewStatus === “Final Draft Reviewed: Approved”) {

wixData.get("Draft Collection", "c03a0570-05cf-4f0a-92cd-33a223293134")
.then((item) => {
  		console.log("Item", item);
		const sourceCollectionId = 'Draft Collection';
		const targetCollectionId = 'Official Collection ';
		const mid = item.mid; // Assuming 'mid' is the field in the source item that maps to the target item
		console.log("Item MID", mid)

		let sourceItem = item;
		let sourceReferences = {};

		const fieldMapping = {
			draftmultiref1: 'pubmultiref1',
			draftmultiref2: 'pubmultiref2',
			draftmultiref3: 'pubmultiref3',
			draftmultiref4: 'pubmultiref4'
		};

		console.log("Item ID", item._id);
		// Step 1: Get the references of the updated source item for all multi-reference fields
		getSourceReferences(sourceCollectionId, item._id, [
			'draftmultiref1',
			'draftmultiref2',
			'draftmultiref3',
			'draftmultiref4',
		])
		
		.then((references) => {
			sourceReferences = references;
			console.log("Original References", references);
			console.log("References", sourceReferences);
			console.log("field mapping", fieldMapping);

			// Step 2: Find the target item by 'mid'
			return wixData.query(targetCollectionId)
				.eq('mid', mid)
				.find();
		})
		.then((results) => {
			if (results.items.length > 0) {
				const targetItem = results.items[0];
				console.log("Target Item", targetItem)
				console.log("Target Item ID", targetItem._id)
				// If the target item exists, update it
				return updateTargetItem(targetCollectionId, targetItem._id, sourceItem)
					.then(() => replaceTargetReferences(targetCollectionId, targetItem._id, sourceReferences, fieldMapping));
			} else {
				// Step 3: If the target item does not exist, insert the source item into the target collection
				return insertTargetItem(targetCollectionId, sourceItem, mid)
					.then((newItem) => replaceTargetReferences(targetCollectionId, newItem._id, sourceReferences, fieldMapping));
			}
		})
		.then(() => {
			console.log('Operation completed successfully');
		})
		.catch((err) => {
			console.error('Error:', err);
		});

		// Function Definitions

		function getSourceReferences(collectionId, itemId, multiReferenceFields) {
			const referencePromises = multiReferenceFields.map(field => 
				wixData.queryReferenced(collectionId, itemId, field)
				.then((results) => {
					return {
						field,
						references: results.items.map(item => item._id)
					};
				})
			);

			return Promise.all(referencePromises)
				.then((results) => {
					const references = {};
					results.forEach(({ field, references: refs }) => {
						references[field] = refs;
					});
					return references;
				});
		}

		function updateTargetItem(collectionId, itemId, sourceItem) {
			return wixData.get(collectionId, itemId)
				.then((targetItem) => {
					// Map fields from sourceItem to targetItem
					targetItem.field1 = sourceItem.field1;
					targetItem.field2 = sourceItem.field2;
					targetItem.field3= sourceItem.field3;
					targetItem.field4 = sourceItem.field4;

					// Add more field mappings as needed

					// Update the target item
					return wixData.update(collectionId, targetItem);
					console.log("Updated Item", targetItem)
				});
		}

		function insertTargetItem(collectionId, sourceItem, mid) {
			let newItem = {
				mid: mid,
				field1: sourceItem.field1,
				field2: sourceItem.field2,
				field3: sourceItem.field3,
				field4: sourceItem.field4,

				// Add more field mappings as needed
			};

			return wixData.insert(collectionId, newItem);
		}

		function replaceTargetReferences(collectionId, itemId, references, fieldMapping) {
			const replacePromises = Object.keys(references).map(sourceField => {
				const targetField = fieldMapping[sourceField];
				console.log(`Replacing references for target field: ${targetField}, source field: ${sourceField}`);
				if (!targetField) {
					console.error(`No mapping found for source field: ${sourceField}`);
					return Promise.resolve(); // Skip this field
				}
				return wixData.replaceReferences(collectionId, itemId, targetField, references[sourceField])
					.catch(err => {
						console.error(`Error replacing references for field ${targetField}:`, err);
					});
			});
		return Promise.all(replacePromises);

}

		item.reviewStatus = "Sync to Live";
		wixData.update("Draft Collection", item);
		console.log ('Item', item)

})
.catch((err) => {
console.log(err);
});

}

However, when I test the code I run into the following errors in the console log:

Error replacing references for field pubmultiref1: Error: WDE0020: Provided property [1cf38796-9f49-4723-b5e8-23b36040fd6d] is not a multi-reference field.

Error replacing references for field pubmultiref2: Error: WDE0020: Provided property [1cf38796-9f49-4723-b5e8-23b36040fd6d] is not a multi-reference field.

Error replacing references for field pubmultiref3: Error: WDE0020: Provided property [1cf38796-9f49-4723-b5e8-23b36040fd6d] is not a multi-reference field.

Error replacing references for field pubmultiref4: Error: WDE0020: Provided property [1cf38796-9f49-4723-b5e8-23b36040fd6d] is not a multi-reference field.

This errors logged are referencing the “replaceTargetReferences” function, and the id in question is logging the id of the item in the collection, which is clearly not a multi-reference field. I’m not sure how to adjust this function for it to work properly. I also double checked the collections and the fieldnames and mapping is all correct. How do I rewrite this section of the code to fix this? Thanks for your help.

Additional Information:

I know I wrote earlier this is ultimately to be used as a data hook. However it is in this format, because it is easier for me to test the code on a test page by directly referencing an item in a collection, rather than testing the update trigger. Once I figure out all the kinks, then I will try to figure out how to test it through the update trigger. If anyone has any tips for this as well, please feel free to share! Thank you!

UPDATE

So I did a bit of digging, and I figured out the problem. It has to do with Wix Data’s replace references function. The itemID and the target Fields values were in the wrong place.

1 Like