AppSync - unable to create a schema with an array when the array property has `#key` directive associated with it - amazon-web-services

I recently added a #key directive to a schema field so that I could search by that field, although I now get an error implying the previously correct data type is not what is expected. It says it expects a string but got a list, although the field is a list containing an enum.
Is it possible to query by a specific field without using #key? If not, how can I create records when the #key (seemingly) changes the expected type of a list to a string?
Below is my code, I added the #key to the categories list, but now when I try to create a new Journey I get the error shown below.
This is the schema:
type Journey #model
#auth(rules: [{ allow: owner, operations: [create, delete, update] }])
#key(name: "getJourneysByCategories", fields: ["categories"], queryField: "getJourneysByCategories")
#key(name: "getJourneysByName", fields: ["name"], queryField: "getJourneysByName") {
id: ID!
name: String!
description: String
coverImage: String
isPrivate: Boolean!
members: [JourneyUsersBridge] #connection(name: "JourneyUsers")
moderators: [JourneyModeratorsBridge] #connection(name: "ModeratedBy")
creator: User! #connection(name: "JourneyCreator")
goals: [Goal] #connection(name: "JourneyGoals")
posts: [Post] #connection(name: "JourneyPosts")
categories: [JourneyCategory!]!
}
This is an example of the code used to create a Journey:
type CreateJourneyInput = {
name: string;
description?: string | null;
coverImage?: string | null;
isPrivate: boolean;
categories: Array<JourneyCategory | null>;
journeyCreatorId: string;
};
const journey: CreateJourneyInput = {
name: 'My GraphQL Journey',
description: 'This Journey was made using GraphQL minus DataStore!',
isPrivate: false,
categories: [JourneyCategory.EXMAMPLE],
journeyCreatorId: userId
};
const result = await API.graphql(
graphqlOperation(mutations.createJourney, { input: journey })
);
This is the full error:
"One or more parameter values were invalid: Type mismatch for Index Key categories Expected: S Actual: L IndexName: getJourneysByCategories (Service: AmazonDynamoDBv2; Status Code: 400; Error Code: ValidationException; Request ID: U4EB7HPO1GU5LHVAOPMGAJJHANVV4KQNSO5AEMVJF66Q9ASUAAJG)"
So I removed the getJourneysByCategories key and the upload worked fine. What's happening here and why?
I just want to be able to query by categories - perhaps #key wasn't the right route to take? Does the key directive not work with lists?

Related

Apollo Federation (Gateway): how to send different "keys" to different implementing microservices?

I am trying to compose a federated apollo service with a gateway and 3 implementing microservices.
MS1:
type Movie #key(fields: "id name") {
id: String!
name: String
}
MS2:
type Location #key(fields: "id") {
id: String!
longitude: Float!
latitude: Float!
}
type Movie #key(fields: "id") #extends {
id: String! #external
location: Location
}
MS3:
type Award #key(fields: "name"){
name: String!
count: Int
}
type Movie #key(fields: "name") #extends {
name: String! #external
award: Award
}
MS1 provides a name and an id.
name shall be send to MS3 for the resolving process and id shall be used by MS2 for the resolving process.
This approach worked with an older version of apollo-gateway / apollo-server, but with the latest versions I receive the following error messages.
{"stack":"Error: A valid schema couldn't be composed. The following composition errors were found:\n\t[ms2] Movie -> extends from ms1 but specifies an invalid #key directive. Valid #key directives are specified by the originating type. Available #key directives for this type are:\n\t#key(fields: \"id name\")\n ...}
An approach to provide the keys like this didn't work either:
type Movie #key(fields: "id") #key(fields: "name") {
What does the schema have to look like to provide the described use case?

How can I append a list object in dynamodb with AWS Amplify and Graphql

When I execute this mutation query (with review id 5) I expect that, when ID 5 is not in the array list, that this will be added to the dynamodb Reviews (type List). But instead the complete Reviews will be overwritten with this object
How can I append or update specific values in de DynamoDB Reviews list array?
mutation CreateUser{
updateObject(input:{id:"d77d2ec2-b4a3-43b7-bb0e-9ef6f1e6fd76", reviews: [{
id:5
score: 8
description: "Ramon11"
email:"jan1111#jan.nl"
}] })
{
id
name
reviews {
id
}
}
}
**In my schema this code is there:**
type Object #model #searchable{
id: ID!
reviews: [Review]
profile: Profile #connection
}
type Review{
id: ID!
score: Int!
description: String!
email: String!
}

AWS Amplify not generating proper graphql input depth

I am new to both graphql & AWS Amplify, so please forgive any ignorance :)
I have a graphql schema like this:
type Location #model #auth(rules: [{allow: owner}]){
street: String
city: String
state: String
zip: String
}
type Trip #model #auth(rules: [{allow: owner}]){
id: String!
...
location: Location
}
I'm trying to create both the location and the trip at the same time with a mutation request like this:
mutation {
createTrip(input: {
id: "someIdentifier",
location: {
street: "somewhere"
}
}) {
id
location {
street
}
}
}
But I'm getting an error like this:
{
"data": null,
"errors": [
{
"path": null,
"locations": [
{
"line": 2,
"column": 21,
"sourceName": null
}
],
"message": "Validation error of type WrongType: argument 'input' with value '...' contains a field not in 'CreateTripInput': 'location' # 'createTrip'"
}
]
}
Checking the generated schema.graphql file, I see that there is indeed no location object on the input model:
input CreateTripInput {
id: String!
...
}
How can I have amplify generate the proper input schema so that I can create both the Trip and the location objects at the same time?
I was able to get an answer from the aws-amplify team here. To summarize:
Both Trip and Location have model directive. There isn't a #connection directive connecting the Trip with Location. The two options to "resolving" this is:
Update the schema connecting the models if you want them to be in 2 separate tables and want the ability to query Trip based on Location. Using 2 separate table you won't be able to create both Trip and Location in a single mutation, though. For example:
type Location #model #auth(rules: [{allow: owner}]){
street: String
city: String
state: String
zip: String
trips: Trip #connection(name:"TripLocation")
}
type Trip #model #auth(rules: [{allow: owner}]){
id: String!
location: Location #connection(name:"TripLocation")
}
The second option, if the Location data is very specific to a trip and you don't want to create a separate table, then get rid of #model directive from your Location type. Doing so would allow you to create Location as a part of same mutation.
type Location {
street: String
city: String
state: String
zip: String
}
type Trip #model #auth(rules: [{allow: owner}]){
id: String!
location: Location
}
The later was the solution that I moved forward with.

AWS AppSync only returns 10 items on query on connection

I'm new to AppSync and trying to see how this works and what's the proper way to set this up.
I created schema.graphql looks like below.
type User #model {
id: String!
following: [String]
follower: [String]
journals: [Journal] #connection(name: "UserJournals", sortField: "createdAt")
notifications: [Notification] #connection(name: "UserNotifications", sortField: "createdAt")
}
type Journal #model {
id: ID!
author: User! #connection(name: "UserJournals")
privacy: String!
content: AWSJSON!
loved: [String]
createdAt: String
updatedAt: String
}
and this created queries.js automatically by AppSync.
export const getUser = `query GetUser($id: ID!) {
getUser(id: $id) {
id
following
follower
journals {
items {
id
privacy
content
loved
createdAt
updatedAt
}
nextToken
}
notifications {
items {
id
content
category
link
createdAt
}
nextToken
}
}
}
`;
I noticed that querying getUser only returns 10 journals items and not sure how to set that to more than 10 or proper way to query and add more journals into that 10 items that were queried by getUser.
Since you do not pass the limit argument explicitly in your query, the Request Mapping Template of the journals resolver defaults it to 10 items. If you would like to change this default value, go to your schema page on the AppSync console, navigate to the journals field, found under the Resolvers section of the schema page. This will then show the resolver definition for this field, and you can then update the default value of 10 to anything you like. Alternatively, you can pass this as your query argument.
FYI - This default value is defined in the amplify-cli repo on GitHub and can be found here.

AWS Appsync resolvers for updated related tables

I am trying to write a resolver for related entities.
Here is how my schema looks.
type User{
id:ID!
name: String!
posts:[Post] #Resolver 1
}
type Post{
id:ID!,
title: String!
body: String!
}
type CreatePostInput{
id:ID!,
title: String!
body: String!
}
type mutation{
addUserPost(userid:ID!, input:CreatePostInput!): Post
}
Now I added a resolver for posts (see #resolver 1) as
{
"version" : "2017-02-28",
"operation" : "Scan",
"key": {
"userid" : { "S" : "${context.source.id}" }
},
}
Now I added a resolver for the mutation addUserPost as
{
"version" : "2017-02-28",
"operation" : "PutItem",
"key": {
"userid" : { "S" : "${context.arguments.userid}" },
"input" : $util.dynamodb.toDynamoDBJson(${context.arguments.input})
}
}
Now when i run the query
mutation addnewposttest{
addChapterToCourse(addUserPost:"c85a0508-ee0e-4ad8-8629-34880e1c6d74",
input:{
title:"Demo",
body:"Test Body",
id: "c85a0508-c85a0-508c-85a-0508"
}){
id
}
}
I get DynamoDB:AmazonDynamoDBException as One or more parameter values were invalid: Missing the key id in the item (Service: AmazonDynamoDBv2; Status Code: 400; Error Code: ValidationException; Request ID: XXXXXXXXXXXX
I tried changing the data source for the second resolver, but with no luck. I did not find any good documentation form AWS except for this , but this talks about simple string data type, not for object type collection.
Can someone help me understand, how to deal with relationships in resolvers? Thanks
I was referring to two separate data tables and to store the data in two tables I need to use BatchUpdate item and specify the table names. However, I could not do it as in my usecase, i had to insert in one table and update in another table.
Finally, I ended up copying the Id in another collection and building an index on it.
This is how my final schema looked
type User{
id:ID!
name: String!
posts:[Post] #Resolver 1 -
}
type Post{
id:ID!,
userId:ID!# I will look for source.id on this field
title: String!
body: String!
}
Thanks everyone for pitching in!
As I commented, you have some update to make.
But the main problem is that your resolver template for addUserPost contains userid but it looks like you need to change it to id. It looks like your User type or the Post type don't have a field named userid