Like what we’re doing? Star us on GitHub!

payload.update help with arrays and hasMany relationship fields

jakehopking
4 weeks ago
10

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

really

helpful 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 đź‘Ť

  • Jarrod
    Payload Team
    4 weeks 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.

  • jakehopking
    4 weeks ago

    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 đź’Ą

Open the post
Continue the discussion in Discord
Can't find what you're looking for?
Get help straight from the Payload team with an Enterprise License.Learn More