Is there a generated "upsert" mutation?

If not, is it possible to define a custom resolver with the SQL needed to perform this operation?

Hi @zach-is-my-name,

We don’t have such functionality now.

Thanks,
Ilya

Hey @zach-is-my-name!

Yeah we currently don’t have a native API operation for merge/upsert. You’d have to tackle it with a custom resolver, which is 100% possible.

npm install -g 8base-cli

8base login

8base init myProject

=> [Select your workspace]

8base g resolver updateOrCreate -s=js

Will give you a template for the resolver.

One strategy might be to accept the table name as the first arg and then the data as the second. This way you could potentially use one resolver for upserting against all your tables.

updateOrCreate('tableName', { title: "Some Title" })

If the fields that you are trying to match don’t have a unique or mandatory constraint, you’ll need to use updateByFilter to search for records to update. For example…

mutation {
  userUpdateByFilter(filter: {
    email: {
      equals: "some@email.com"
    }
  }, data: {
    email: {
      set: "somenew@email.com"
    },
    firstName: {
      set: "Steve"
    },
    lastName: {
      set: "Jones"
    }
  }) {
    count
  }
}

In this case, if the count returned 0 you’d then want to make a create request using the same data.

Hope this helps and feel free to ask more questions.

Sebastian

1 Like

I’d love to be able to do upsert within relations as I’m sometime not 100% sure a child already exists or not. Is there any way to bring a custom resolver within the create/update/connect/reconnect/disconnect interface @sebastian.scholl?

Hey @gahabeen! If you write a before trigger on update operation on a table, it will always run before a record in that table is updated - whether or not it’s being called directly or through a relationship.

That said, if you set a before trigger on update on the parent table, you’ll be able to check the payload for an update happening on the related record… For example:

// function code

if (event.data.childRelationship.update) {
  const { childRecord } = await ctx.api.gqlRequest(FIND_RECORD_QUERY, {
    uniqueIdentifier: event.data.childRelationship.update.uniqueIdentifier;
  });

  if (!childRecord) {
    event.data.childRelationship['create'] = event.data.childRelationship.update;
    delete event.data.childRelationship.update;
  }
}

// maybe... more code

return {
  data: event.data
}

Given that something like this would happen before the update, you’d be able to change the relational data passed to the update operation before it gets executed.

Let me know if this makes sense or helps you get on the right track.

1 Like

Thanks, I definitely need to use more of the trigger’s power!
I really like your idea :slight_smile:

1 Like