How to update all records in a collection using graphql

被刻印的时光 ゝ 提交于 2019-12-21 17:54:02

问题


I'm using Graph.cool graphql as a service and am wondering how to do a mass update to the collection, similar to a SQL update.

In my case I need to update the suffix of a url, in the imageUrl column of my database. I need to swap out a {someid}_sm.jpg to {someid}_lg.jpg

How do I do that with a graphql mutation? I don't want to reload the entire dataset again and am looking for a way to do it that doesn't involve manually interating through the entire list with a graphql client.

mutation {
  updatePost() // what goes here?
}

回答1:


Migration script

The best approach is indeed to use a migration script that combines multiple mutations so only one HTTP request is sent to the GraphQL backend.

Consider this schema:

type Image {
  id: ID!
  name: String!
}

We can include the same mutation multiple times in one request with GraphQL aliases:

mutation {
  first: updateImage(id: "first-id", name: "01_lg.jpg") {
    id
    name
  }

  second: updateImage(id: "second-id", name: "02_lg.jpg") {
    id
    name
  }
}

We'll make use of this mechanism in our migration script. I'll describe it with Lokka and Node, however you can choose whatever language and GraphQL client you prefer.

First, we query all existing images to obtain their id and name:

const queryImages = async() => {
  const result = await client.query(`{
    images: allImages {
      id
      name
    }
  }`)

  return result.images
}

Then we replace the names accordingly and construct one big request including the necessary updateImage mutations with a different GraphQL alias for each.

If your image names might contain the string sm in the {someid} part mentioned in your question, this script will break! In that case, please adjust accordingly.

const migrateImages = async(images) => {
  // beware! if your ids contain the string 'sm', adjust the string replacement accordingly!
  const updateMutations = _.chain(images)
    .map(image => ({ id: image.id, name: image.name.replace('sm', 'lg')}))
    .map(image => `
      ${image.id}: updateImage(id: "${image.id}", name: "${image.name}") {
        id
        name
      }`)
    .value()
    .join('\n')

  const result = await client.mutate(`{
    ${updateMutations}
  }`)

  console.log(`Updated ${Object.keys(result).length} images`)
  console.log(result)
}  

That's it. If you have to update thousands of images, batching the mutations in say groups of a hundred might be better than to batch all of them in one request. Note that mutations run sequentially on the GraphQL server.

Running the migration

Currently, I suggest the following workflow for running the migration:

  • Clone your project
  • Run the migration script on your cloned project
  • Verify that the migration ran successfully. Double check :)
  • Run the migration on your original project

You can find the code and further instructions here.

While this approach is great for migrations that are as straightforward as in your example, it's not perfect for all situations. We're already thinking about creating an integrated experience for this use case, such as an interactive migration right in your Graphcool project, with simulated migrations, checks and more. If you have suggestions, let me know in Slack.



来源:https://stackoverflow.com/questions/41688883/how-to-update-all-records-in-a-collection-using-graphql

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!