GraphQL API: Upsert (add or update) operation? updateBatch?

Looking for an equivalent of an upsert mutation so I can perform add or update operations based on whether a particular ID exists in the database.

For example, lets say have a dynamic data source that looks something like this:

Record ID Name # of Cats
A Dave 0
B Alex 1
C Tanya 9

And I’m trying to periodically sync all those records and their latest data into my Fibery database, which currently looks like this:

Fibery Entity ID Record ID Name # of Cats
0c3 C Tanya 8
7p4 D Jade 0
6e8 E Chris 2

So the the sync would have to look something like this:

  1. Check what records in my data source already have a matching entity in my Fibery database using the Record ID
  2. Update the matching entities in my Fibery database
  3. Add to my Fibery database the rest of the “new” records in my data source

So at the end of the upsert operation my Fibery database would look like this:

Fibery Entity ID Record ID Name # of Cats
0c3 C Tanya 9
7p4 D Jade 0
6e8 E Chris 2
n4w A Dave 0
z02 B Alex 1

I got about this far and then ran into the issue where I’m not familiar with GraphQL and wasnt sure how to do batch update operations for matching records:

mutation {
  catTracker(recordId:{in:["B", "C"]}) {
    updateBatch(data: [{name: "Alex"}, {name: "Tanya"}]) {
      message
    }
  }
}

Hi, @Dimitri_S

Batch update can be used to perform multiple mutations over set of records. It means that when you find some records you can perform the same mutations for these records. Your mutation

updateBatch(data: [{name: "Alex"}, {name: "Tanya"}]) {
      message
    }

will not have sense since it will update records B and C with the same name “Tanya” last met name update mutation.

The possible example of updateBatch can be

updateBatch(data:[
   {effort: 13},
   {name: `Update name`}   
])

If you would like to perform different changes to records just use several mutations.

Thanks,
Aleh

@Dimitri_S

However your mentioned upsert mutation is a very good idea. We will think about adding it.

Thanks,
Oleg

1 Like

Sorry but I still don’t understand how updateBatch would be used. Can you please provide an example and maybe add it to the GraphQL docs?

In the docs it looks like you can update multiple records at once just by using update, so why use updateBatch?

mutation {
  bugs(effort:{is: 15}, state:{name:{is:"To Do"}}){
    update(
      release:{name:{is:"1.0"}}
      effort: 10
    ){entities{id}}
    countOfEntities
  }
}

I’ve spend a while now and still can’t figure out how to do the kind of updates I want using GraphQL without hundreds of requests. Can you please assist? Here is another example of what I am trying to do:

const dataSource = [
    {name: 'Dave', cats: 0},
    {name: 'Alex', cats: 1},
    {name: 'Tanya', cats: 9},
]

const fiberyDb = [
    {name: 'Tanya', cats: 8},
    {name: 'Jade', cats: 0},
]

// trying to do the equivalent of this in GraphQL
dataSource.forEach(sourceRecord => {
    const fiberyEntity = fiberyDb.find(entity => entity.name == sourceRecord.name)
    fiberyEntity ? Object.assign(fiberyEntity, sourceRecord) : fiberyDb.push(sourceRecord);
})

console.log(fiberyDb)
// [ { name: 'Tanya', cats: 9 },
//   { name: 'Jade', cats: 0 },
//   { name: 'Dave', cats: 0 },
//   { name: 'Alex', cats: 1 } ]

yes. you are right about that. updateBatch was made just as others methods like createBatch. there is no much sense to have it.

So to clarify, if I want to apply a different update to 5 separate records I need to do 5 separate GraphQL API requests? Or is there a way to do many different update mutations in a single GraphQL API request.

EDIT: I think this might be the way to update multiple records in one request, is this suitable for 100s of updates at once?

mutation {
  n1: catTrackers(name: {is: "Tanya"}) {
    update(cats: 9) {
      message
    }
  }
  n2: catTrackers(name: {is: "Alex"}) {
    update(cats: 1) {
      message
    }
  }
}
1 Like

@Dimitri_S

Please use multiple requests. Also I suggest to use paging if mutations applied for a huge amount of records. The explanation can be found Fibery GraphQL API

1 Like

Any chance this might have been worked on or can be added to the roadmap?

@Dimitri_S

Hello, there are some difficulties with selected GraphQL framework to have that implemented. Unfortunately, can not say when it will done.

Maybe our set-up can be useful for the ones reading this and waiting for the Upsert functionality.

  • We first try to update the entity without do a find upfront.
  • When the entity exists, we update the entity. If the entity doesn’t exist, we get a payload that includes { “update”: null }
  • We have some logic that when the payload gives the above response, we then create a new entity since it doesn’t exist.

Most of the time the entity already exists. In our experience this is faster than first do a query to check if the item exists yes/no.

For now, we only do this with single items. We haven’t tried if it also works with batches.

Upsert would be still very handy since we have a lot of data to process and it will save a call when an item doesn’t exists.