FaunaDB-如何批量更新单个graphQL突变内的条目列表?

问题描述 投票:1回答:1

我想在动物群中批量更新带有graphQL突变的条目列表。输入数据是来自外部来源的冠状病毒病例列表。它将经常更新。如果collectio中存在条目名称,则该突变应更新现有条目,如果不存在则创建新条目。

当前GRAPHQL更改

mutation UpdateList($data: ListInput!) {
  updateList(id: "260351229231628818", data: $data) {
    title
    cities {
      data {
        name
        infected
      }
    }
  }
}

GRAPHQL变量

{
  "data": {
    "title": "COVID-19",
    "cities": {
      "create": [
        {
          "id": 22,
          "name": "Warsaw",
          "location": {
            "create": {
              "lat": 52.229832,
              "lng": 21.011689
            }
          },
          "deaths": 0,
          "cured": 0,
          "infected": 37,
          "type": "ACTIVE",
          "created_timestamp": 1583671445,
          "last_modified_timestamp": 1584389018
        }
      ]
    }
  }
}

SCHEMA

type cityEntry {
  id: Int!
  name: String!
  deaths: Int!
  cured: Int!
  infected: Int!
  type: String!
  created_timestamp: Int!
  last_modified_timestamp: Int!
  location: LatLng!
  list: List
}

type LatLng {
  lat: Float!
  lng: Float!
}

type List {
  title: String!
  cities: [cityEntry] @relation
}

type Query {
  items: [cityEntry!]
  allCities: [cityEntry!]
  cityEntriesByDeathFlag(deaths: Int!): [cityEntry!]
  cityEntriesByCuredFlag(cured: Int!): [cityEntry!]
  allLists: [List!]
}

每次运行突变都会创建新的重复项。在单个突变内更新列表的最佳方法是什么?

graphql bulk mutation faunadb
1个回答
1
投票

抱歉,抱歉,我不确定丢失的信息是什么,因此为什么我先发表评论:)。

模式

具有参数的模式的一部分的示例:

type Mutation {
  register(email: String!, password: String!): Account! @resolver
  login(email: String!, password: String!): String! @resolver
}

当在FaunaDB中导入这样的架构时,将提供占位符功能。

UDF参数

Function stubs

如您所见,该函数所做的全部就是中止,并显示消息,该函数仍必须实现。该实现从一个Lambda开始,该Lambda接受参数,并且这些参数必须与您在解析程序中定义的参数匹配。

Query(Lambda(['email', 'password'],
    ... function body ...
))

使用参数是通过Var完成的,在这种情况下,这意味着Var('email')或Var('password')。例如,在我的特定情况下,我们将使用传递来的电子邮件通过电子邮件获取帐户,并使用密码传递给Login函数,该函数将返回一个秘密(我在此处进行选择的原因是GraphQL解析器的返回值必须是有效的GraphQL结果(例如,纯JSON

Query(Lambda(['email', 'password'],
    Select(
      ['secret'],
      Login(Match(Index('accountsByEmail'), Var('email')), {
        password: Var('password')
      })
    )
))

通过GraphQL调用UDF解析器

最后,调用时如何传递参数?从GraphQL游乐场应该很清楚,因为它将为您提供文档和自动完成功能。例如,这是在架构导入后自动生成的GraphQL文档告诉我的内容:

enter image description here

这意味着我们可以这样称呼它:

mutation CallLogin {
  login (
    email: "<some email>"
    password: "<some pword>"
  )
}

批量更新

对于批量更新,还可以将值列表传递给用户定义的函数(UDF)。假设我们要通过UI将多个帐户分组到一个特定的团队中,因此希望同时更新多个帐户。

我们的模式中的突变可能如下所示(GraphQL中的ID与字符串相似)

type Mutation { updateAccounts(accountRefs: [ID]): [ID]! @resolver } 

然后,我们可以通过提供从FaunaDB接收到的ID来调用变异(如果您混合使用FQL和GraphQL,则为字符串,而不是Ref,如果您仅使用GraphQL,则不必担心)。

mutation {
    updateAccounts(accountRefs: ["265317328423485952", "265317336075993600"] )
}

就像以前一样,我们必须填写FaunaDB生成的用户定义函数。一个仅接受数组并返回它的骨架函数将看起来像:

Query(Lambda(['arr'], 
  Var('arr')
))

有些人可能已经看过一种更简单的语法,因此很容易使用它:

Query(Lambda(arr => arr))

但是,此当前在通过数组传递时目前不适用于GraphQL,这是一个已知问题,将得到解决。下一步是实际遍历数组。 FQL不是声明性的,而是从功能语言中汲取灵感的,这意味着您只需使用“ map”或“ foreach”即可做到这一点]

Query(Lambda(["accountArray"], 
  Map(Var("accountArray"), 
  Lambda("account", Var("account")))
))

我们现在遍历该列表,但由于我们只是退还了帐户,因此对其不做任何处理。现在,我们将更新帐户,并在那里设置一个值“ teamName”。为此,我们需要Update函数,该函数需要一个FaunaDB Reference。 GraphQL向我们发送字符串而不是引用,因此我们需要将这些ID字符串转换为带有Ref的引用,如下所示:

 Ref(Collection('Account'), Var("account"))

如果将所有内容放在一起,我们可以向帐户ID列表中添加一个额外的属性,如下所示:

Query(Lambda(["accountArray"], 
  Map(Var("accountArray"), 
    Lambda("account", 
       Do(
         Update(
          Ref(Collection('Account'), Var("account")),
          { data: { teamName: "Awesome live-coders" } }
        ),
        Var("account")
      )
    )
  )
))

在地图的末尾,我们只是使用Var(“ account”)再次返回该帐户的ID,以返回纯JSON格式的内容,否则我们将返回FaunaDB Ref,而不仅仅是JSON和不会被GraphQL调用接受。

enter image description here

传递更复杂的类型。

有时您想传递更复杂的类型。假设我们有一个简单的待办事项架构。

type Todo {
  title: String!
  completed: Boolean!
}

并且我们要将具有特定标题的待办事项列表的完整值设置为true。我们可以在FaunaDB生成的扩展模式中看到一个TodoInput。

enter image description here

但是它似乎很烦人,因为您在创建时没有架构的那部分,因此不能只写:

type Mutation { updateTodos(todos: [TodoInput]): Boolean! @resolver } 

因为它将返回以下错误。enter image description here

但是,我们可以将其自己添加到架构中。

type Todo {
  title: String!
  completed: Boolean!
}

input TodoInput {
  title: String!
  completed: Boolean!
}

type Mutation { updateTodos(todos: [TodoInput]): Boolean! @resolver } 

这意味着我现在可以写:

mutation {
  updateTodos(todos: [{title: "test", completed: true}])
}

并进入FQL函数以使用此输入执行操作。或者,如果您想在数据中包含ID,则可以定义一个新类型。

input TodoUpdateInput {
  id: ID!
  title: String!
  completed: Boolean!
}
type Mutation { updateTodos(todos: [TodoUpdateInput]): Boolean! @resolver } 

一旦掌握了它,并想了解更多有关FQL的知识(这是一个完全不同的主题),我们目前正在撰写一系列文章以及其中第一个出现在此处的代码:https://css-tricks.com/rethinking-twitter-as-a-serverless-app/,这可能是一个不错的选择温柔的介绍。

© www.soinside.com 2019 - 2024. All rights reserved.