What is the recommended approach for updating array and hasMany relationship fields?
### 1) hasMany relationship fields
I have an Customer collection, and I want to add an order id to the hasMany relationship field. What's the approach to take here?
### 2) array fields
If I want to push a new object to an array, what is the recommended approach here?
Some example code for both cases would be
reallyhelpful here.
Thanks!
@payloadcms team - would really appreciate a guide here.
When we create a relationship field, it produces an array at the API level, but when I add a new
id
to the field through
payload.update()
do we again treat is as an array?
Would this be a correct approach:
const payloadCustomer: CustomerType = await payload.findByID({
collection: 'customers',
id: newOrUpdatedOrder.customerRelationship.id,
});
if (payloadCustomer.stripe.customerId === '') {
const stripeCustomer = await stripe.customers.create({
email: customer.email,
name: customer.name,
address: customer.address,
});
const updatedCustomer: CustomerType = await payload.update({
collection: 'customers',
id: payloadCustomer.id,
data: {
stripeCustomerId: stripeCustomer.id,
orders: [
...payloadCustomer.orders,
newOrUpdatedOrder.id,
],
},
});
}
and if the
hasMany
is set to false, how do we treat this field from
payload.update
is it an array of length 1, or is it a string of id?
I've found the docs have been updated since the last time I checked many moons ago 👍
Hey @jakehopking to update an array (relationship or not), you need merge the existing array data with the new one as you are doing above.
Of fundamental importance for anyone who gets stuck on this for more time than they should:
You need to map over the array you intend to spread back in, and only return the
id
.
A relationship
hasMany
only stores an array of id, and when we query with say,
payload.findById
it returns these populated as would be expected, so when you spread back in, then you need to filter out everything except the id. Like so:
orders: [
...payloadCustomer.orders.map((order) => order.id),
newOrUpdatedOrder.id,
],
@Jarrod Thanks, but I'm still a bit confused. The above realisation got me most of the way.... however I notice that the
hasMany
can actually hold arrays with multiple items with the same id. Is this expected? How best to filter out?
do I need to do something like this to ensure no duplicates??
orders: Array.from(
new Set([
...payloadCustomer.orders.map((order) => order.id),
newOrUpdatedOrder.id,
]),
),
-
seems like this should be handled at the api level?
-
For completeness for others learning this, if the hasMany relationship is new and therefore empty you need to cater for that like so:
orders: Array.from(
new Set([
...(payloadCustomer?.orders?.length > 0
? payloadCustomer.orders.map((order) => order.id)
: []),
newOrUpdatedOrder.id,
]),
),
Otherwise you'll get undefined errors on the map and everything explodes đź’Ą