如何使用graphql更新集合中的所有记录

时间:2017-01-17 04:04:27

标签: graphql graphcool

我正在使用Graph.cool graphql作为服务,我想知道如何对集合进行批量更新,类似于SQL更新。

在我的情况下,我需要在数据库的imageUrl列中更新url的后缀。我需要将{someid} _sm.jpg换成{someid} _lg.jpg

如何使用graphql变异做到这一点?我不想再次重新加载整个数据集,并且正在寻找一种不需要使用graphql客户端手动整理整个列表的方法。

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

1 个答案:

答案 0 :(得分:5)

迁移脚本

最好的办法确实是使用一个结合multiple mutations的迁移脚本,因此只有一个HTTP请求被发送到GraphQL后端。

考虑这个架构:

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

我们可以使用GraphQL别名在一个请求中多次包含相同的突变:

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

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

我们将在迁移脚本中使用此机制。我将使用Lokka和Node来描述它,但您可以选择您喜欢的任何语言和GraphQL客户端。

首先,我们查询所有现有图片以获取他们的idname

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

  return result.images
}

然后我们相应地替换名称并构造一个大的请求,包括必要的updateImage突变,每个突变使用不同的GraphQL别名。

如果您的图片名称可能包含问题中提到的sm部分中的字符串{someid},则此脚本将会中断!在这种情况下,请进行相应调整。< / p>

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)
}  

那就是它。如果你必须更新成千上万的图像,那么将突变分组为一百个组可能比在一个请求中批量处理所有这些更好。请注意GraphQL服务器上的mutations run sequentially

运行迁移

目前,我建议使用以下工作流程来运行迁移:

  • 克隆您的项目
  • 在克隆项目上运行迁移脚本
  • 验证迁移是否成功运行。仔细检查:)
  • 在原始项目上运行迁移

您可以找到代码和更多说明here

虽然这种方法对于像您的示例一样简单的迁移非常有用,但它并不适用于所有情况。我们已经在考虑为此用例创建集成体验,例如Graphcool项目中的交互式迁移,模拟迁移,检查等。如果您有任何建议,请在Slack中告知我们。