我想在动物群中批量更新带有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!]
}
每次运行突变都会创建新的重复项。在单个突变内更新列表的最佳方法是什么?
抱歉,抱歉,我不确定丢失的信息是什么,因此为什么我先发表评论:)。
具有参数的模式的一部分的示例:
type Mutation {
register(email: String!, password: String!): Account! @resolver
login(email: String!, password: String!): String! @resolver
}
当在FaunaDB中导入这样的架构时,将提供占位符功能。
如您所见,该函数所做的全部就是中止,并显示消息,该函数仍必须实现。该实现从一个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游乐场应该很清楚,因为它将为您提供文档和自动完成功能。例如,这是在架构导入后自动生成的GraphQL文档告诉我的内容:
这意味着我们可以这样称呼它:
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调用接受。
有时您想传递更复杂的类型。假设我们有一个简单的待办事项架构。
type Todo {
title: String!
completed: Boolean!
}
并且我们要将具有特定标题的待办事项列表的完整值设置为true。我们可以在FaunaDB生成的扩展模式中看到一个TodoInput。
但是它似乎很烦人,因为您在创建时没有架构的那部分,因此不能只写:
type Mutation { updateTodos(todos: [TodoInput]): Boolean! @resolver }
但是,我们可以将其自己添加到架构中。
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/,这可能是一个不错的选择温柔的介绍。