Well, I gave up on this issue and now do 2 different (actually 3) different mutations. I guess this is not the way it is supposed to be but at least it works for me…
For completeness, I post my solution. Let’s assume that we have:
- an external ID (email with @id directive)
- an Edge
Role
on the parent node User
with an Enum Type
- an Edge
Organisation
on the parent node User
as an Array of nodes
The Setup
type User {
id: ID!
email: String! @id
role: Role!
organisations: [Organisation!]!
}
type Role {
id: ID!
type: RoleType!
}
enum RoleType {
"ADMIN"
"MEMBER"
}
type Organisation {
id: ID!
name: String!
}
In order to update the email field with the @id directive, we need to execute a DQL mutation. I do this with
const dqlUpdate = await dql.mutate(`{
set {
<${input.userId}> <User.email> "${input.email}" .
}
}`);
Since I could not find out how to update the edges of the parent node with DQL, I do this with a GraphQL mutation. Let’s start with the role
field first since updating arrays is still a bit more complicated
const graphQlUpdate = await graphql(`
mutation(
$id: [ID!]
$roleId: ID!
) {
updateUser( input: {
filter: { id: $id },
set: {
role: {
id: $roleId
}
}
}) {
numUids
}
}
`, { ...input });
When updating arrays of edges (or references), we have to remove and add the references within the mutation. Since my array isn’t that large I always remove the entire array first and then add my new array. This mean I can extend the above mutation
const graphQlUpdate = await graphql(`
mutation(
$id: [ID!]
$roleId: ID!
$addOrgs: [OrganisationRef!]
$removeOrgs: [OrganisationRef!]
) {
first: updateUser( input: {
filter: { id: $id },
remove: { organisations: $removeOrgs },
set: {
role: {
id: $roleId
}
}
}) { numUids }
second: updateUser( input: {
filter: { id: $id },
set: {
organisations: $addOrgs
}
}) { numUids }
}
`, { ...input });
The complete lambda would then be
async function amendUser({ args, dql, graphql }) {
const { input } = args;
const dqlUpdate = await dql.mutate(`{
set {
<${input.id}> <User.email> "${input.email}" .
}
}`);
const graphQlUpdate = await graphql(`
mutation(
$id: [ID!]
$roleId: ID!
$addOrgs: [OrganisationRef!]
$removeOrgs: [OrganisationRef!]
) {
first: updateUser( input: {
filter: { id: $id },
remove: { organisations: $removeOrgs },
set: {
role: {
id: $roleId
}
}
}) { numUids }
second: updateUser( input: {
filter: { id: $id },
set: {
organisations: $addOrgs
}
}) { numUids }
}
`, { ...input });
return { success: "Yay!" }
}
I still don’t think this is the right way of doing this but it works… Any suggestions welcome!