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

How to update all records in a collection using graphql

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

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

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

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

迁移脚本

最好的方法确实是使用结合 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 别名。

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

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.

中告诉我