Cannot perform update query because update values are not defined - graphql

I am trying to execute a mutation like so
mutation creating {
createTeam(
payload: {
name: "Team von abc"
tacts:["94b4cbc2-b996-482f-b712-967bdb646e73"]
}
) {
id
name
}
}
This results in :
"message": "Cannot perform update query because update values are not
defined. Call \"qb.set(...)\" method to specify updated values.",
My graphql is defined like this:
input CreateTeamPayload {
name: String
tacts:[ID!]
}
type Team {
id: ID!
name: String
tacts: [Tact]!
}
type Query {
fetchTeams: [Team]!
fetchTeamById(id: ID!): Team
}
type Mutation {
createTeam(payload: CreateTeamPayload): Team!
}
My Team requires an ID from a "tact" so I provide him with an ID from a "tact" I created before. Is this approach wrong? How can I mutate types that reference other types? is there some documentation that actually does this?

Related

Error Cannot return null for non-nullable type: 'String' within parent MyModelType' (/createMyModelType/id)

I am trying to trigger a mutation in the aws console. I have linked my resolver function to a None type data source.
However, when I define my mutation with an input type as a parameter, the error " Error Cannot return null for non-nullable type: 'String' within parent MyModelType' (/createMyModelType/id)." occurs. Everything is fine though if I replace the input type with key word arguments.
I am certain it has to do with my resolver mapping template.
Just if you're wondering why I am using a None type, I want to be able to trigger a subscription without making real database changes or mutations.
I am not sure how to make it work with input types. Here is my code for the template:
{
"version": "2017-02-28",
"payload": $util.toJson($context.args)
}
My Schema:
input CreateMyModelType5Input {
title: String
}
type Mutation {
createMyModelType5(input: CreateMyModelType5Input!): MyModelType5
}
type MyModelType5 {
id: ID!
title: String
}
type Subscription {
onCreateMyModelType5(id: ID, title: String): MyModelType5
#aws_subscribe(mutations: ["createMyModelType5"])
}
Query I am trying to run:
mutation createMyModelType($createmymodeltypeinput: CreateMyModelTypeInput!) {
createMyModelType(input: $createmymodeltypeinput) {
id
title
}
}
Query Variables for the mutation query
{
"createmymodeltype5input": {
"title": "Hello, world!"
}
}
So I have been working on passing my arguments in the graphql mutation and using the input type seemed the only straight forward way around.
However, I have been able to do it with this way:
mutation = """mutation CreateMyModelType($id: String!, $title: String!){
createMyModelType(id: $id, title: $title){
id
title
}
}
"""
input_params = {
"id": "34",
"title": "2009-04-12"
}
response = app_sync.createMyModelType(mutation, input_params)
this can be a good guide

GraphQL query with multiple nested resolvers and mapping fields to arguments

From GraphQL Client's perspective, how do I perform a query with multiple nested resolvers where the fields from the parent are passed as arguments to the child resolver?
Here is a minimal example:
GraphQL Schema:
type Author {
id: ID!
name: String!
}
type Book {
id: ID!
title: String!
releaseDate: String!
}
type Query {
// Returns a list of Authors ordered by name, 'first' indicates how many entries to return
getAllAuthors(first: Int!): [Author]!
// Returns a list of Books ordered by releaseDate, 'first' indicates how many entries to return
getBooksByAuthorId(first: Int! authorId: ID!): [Book]!
}
Is it possible to write a query to get all authors and their last released book? Something around the lines:
query GetAuthorsWithLastBook($first: Int!) {
getAllAuthors(first: $first) {
authorId: id
name
lastBook: getBooksByAuthor(1, authorId) {
title
}
}
}
In the example above, I attempted to alias getAllAuthors.id as authorId and pass the alias down as argument to getBooksByAuthor(...) but that didn't work.
The key aspect of the problem is that I don't know the authorIds beforehand. I could fetch the authors first and build a query to fetch their last book but that will result in multiple queries and that is something I would like to avoid.
Update
A Java Kickstarter example is available here: https://www.graphql-java-kickstart.com/tools/schema-definition/
yes, on the graphql definition, you need to add lastBook in the Author
type Author {
id: ID!
name: String!
lastBook: [Book]
}
Next up u need to write the resolver for the lastBook
const resolvers = {
Query: {
Author {
lastBook: (parent, args) {
const userId = parent.id;
return getBooksByAuthor(userId, 1);
},
}
}
};

graphql - Refer to other fields in mutation

I want to create 2 related objects, e.g. 1 Location and 1 Place where Place has a reference to Location like so:
type Location {
id: String
name: String
}
type Place {
id: String
locationId: String
}
Is it possible to do this with 1 mutation request? Currently I'm doing this with 2 separate mutation requests like below:
mutation ($locationName: String!) {
insert_Location(objects: {name: $locationName}) {
returning {
id
}
}
}
//in another request, use the id returned from the request above
mutation ($locationId: String!) {
insert_Place(objects: {locationId: $locationId}) {
returning {
id
}
}
}
I'm aware it's possible to have multiple fields in a mutation so I could create 2 Locations in 1 mutation request like below.
mutation ($locationName: String!) {
location1: insert_Location(objects: {name: $locationName}) {
returning {
id
}
}
location2: insert_Location(objects: {name: $locationName}) {
returning {
id
}
}
}
However if I wanted to do this to create 1 Location and 1 Place, is there a way to retrieve the created Location Id and pass it to the 2nd field to create the Place?
For future reference:
As #Xetera pointed out, because the 2 types have a foreign key relationship you can do a nested insert mutation where hasura would handle setting the foreign key value. In my case it would look something like:
mutation ($locationName: String!) {
insert_Place(
objects: {
Location: {data: {name: $locationName}}, //hasura will create Location and assign the id to Place.locationId
}
) {
returning {
id
}
}
}
Docs here for further reading: https://hasura.io/docs/1.0/graphql/manual/mutations/insert.html#insert-an-object-along-with-its-related-objects-through-relationships

How can I insert records in AwsAppSync mutation with proper #connection values?

I have added a resources table to my schema, connecting to a Plants table:
type Resource #model
{
id: ID!
name: String!
Plants: [Plant] #connection(name: "ResourcePlant")
}
Ran amplify push, and all resources were created properly.
Now I wanted to add a Resource, and link it to all Plants properly.
Do you know how is the sintaxe I should use to run the recently created mutation createResource in order to add the items on Plant I want to include to that resource?
I tried to run like this:
mutation CreateResource {
createResource (input: {
name: "Plant",
Plants : {
items :
{ id: "f9a0468e-da74-41d5-8287-1cb6a76b25a5" }
}
}
) {
name,
Plants {
items {
id
}
nextToken
}
}
}
This was the error message:
Validation error of type WrongType: argument 'input' with value
'ObjectValue{objectFields=[ObjectField{name='name',
value=StringValue{value='Plant'}}, ObjectField{name='Plants',
value=ObjectValue{objectFields=[ObjectField{name='items', value=ObjectValue{objectFields=[ObjectField{name='id',
value=StringValue{value='f9a0468e-da74-41d5-8287-1cb6a76b25a5'}}]}}]}}]}'
contains a field not in 'CreateResourceInput': 'Plants' # 'createResource'
How did you define Plant?
And have you checked this example? https://aws-amplify.github.io/docs/cli-toolchain/graphql#connection
Ok, after some headache, I found what was missing in my model. For me so far it has proved to be the best way of doing this relationship...
I have added on my Plant type, on schema definition, a field named plantResourceId (other than the one used for the #connection directive). What I found out was that, by convention, when inserting/updating a record on "Plant" and adding the resource "id" field content of the resource I want to "connect" to that plant, it will automatically be retrieved when "Resources" is queried, for each item - what is better: Out-of-the-box from codegen.
Insert example
mutation CreatePlant {
createPlant(input:{
name: "MyPlant",
plantResourceId: "id-for-connected-resource"
}) {
name,
plantResourceId
}
}
Query example to retrieve items:
query listPlantsOnResource {
listResources(filter: {
name: {
contains: "myfilter"
}
}) {
items {
id
name
Plants
{
items {
id
name
description
}
}
}
}
}
It worked very well!
Thanks all who contributed!

Create mutation between related types in GraphQL

I'm using GraphQL to try to create a record that has a relation to another type. The types are Task and Day
datamodel.graphql:
type Task {
id: ID! #unique
content: String!
completed: Boolean!
dateToDo: Day!
}
type Day {
id: ID! #unique
content: String!
tasks: [Task]
}
I want to create a task so that it has a reference of the date it should be completed (from the Day type)
schema.graphql
type Mutation {
createTask(content: String!, completed: Boolean!, dateToDo: ID! ): Task!
}
my mutation resolver looks like this:
const Mutations = {
async createTask(parent, args, ctx, info) {
const task = await ctx.db.mutation.createTask(
{
data: {
dateToDo: {
connect: {
id: args.dateToDo
}
},
...args
}
},
info
);
return task;
},
when I run this mutation to create the task:
mutation CREATE_ONE_TASK {
createTask(
content: "a new task",
completed: false,
dateToDo: "cjqycv9dtjklr09179y9zfntq")
{
id
}
}
I get this error:
"message": "Variable \"$_v0_data\" got invalid value
{\"dateToDo\":\"cjqycv9dtjklr09179y9zfntq\",\"content\":\"a new
task\",\"completed\":false}; Expected type
DayCreateOneWithoutTasksInput to be an object at value.dateToDo.",
My questions are: Am I using connect correctly in the mutation resolver? And what the heck is DayCreateOneWithoutTasksInput (I see its been automagically added in prisma.graphql) and how do I use it to create a Task that has a relation to a Day's ID?
The mutation to create the task has the following shape:
mutation b {
createTask(
data: {
content: "Task1"
completed: false
dateToDo: { connect: { id: "cjqzjvk6w000e0999a75mzwpx" } }
}
) {
id
}
}
The type DayCreateOneWithoutTasksInput Prisma is asking for is autogenerated and is the one expected for the field dataToDo. The name means that Prisma would accept a type that creates one Day node but does not have the field tasks or a type that specifies a connection. The WithoutTasksInput part states is there because the type can only be used nested in a mutation where you start from a task, Prisma therefore already has the value to fill in for the tasks field on the nested Day node and you do not need to specify it if you create the day instead of connecting an existing one.
If you use the Playground you can explore the schema that contains all the types on the right side.
schema explorer in the playground
Hope that helps!

Resources