Given the GraphQL Schema:
schema {
query: Query
mutation: Mutation
subscription: Subscription
}
type Mutation {
addPost(id: ID! author: String! title: String content: String url: String): Post!
updatePost(id: ID! author: String! title: String content: String url: String ups: Int! downs: Int! expectedVersion: Int!): Post!
deletePost(id: ID!): Post!
}
type Post {
id: ID!
author: String!
title: String
content: String
url: String
ups: Int
downs: Int
version: Int!
}
type Query {
allPost: [Post]
getPost(id: ID!): Post
}
type Subscription {
newPost: Post
}
We see that the addPost expects a Post type. So in the resolver function of addPost, we need to retrieve all the data that form a Post type from database, right? But what we are gonna do in our resolver function is to send a PutItem (ex.) request to Post table in database without getting all the data back from database. Then where do we get the data needed for Post type to pass to the children resolvers?
Is there some misunderstanding for me on how resolvers work?
Related
I want to create an action with the following input:
input PurchaseInput {
user: UserInfo!
}
UserInfo is defined as an object:
type UserInfo {
accessToken: String!
userId: Int!
}
However Hasura doens't like this and returns a 400 on saving the action.
Is it possible to define custom input types in Hasura? I feel limited by String, Int, Float, Boolean etc.
You can absolutely create custom types like in your example
type UserInfo {
accessToken: String!
userId: Int!
}
So the error is of some other origin ( action response.... ).
Hasura only has a limitation of nested object types, for example, you can not do type definition like this in action :
type User {
userId: Int!
}
type UserInfo {
accessToken: String!
user: User!
}
How can we get the User Conversations with a query. Ideal would be to do a query to the user table and get all the user conversations loaded.
example:
final user = await Amplify.DataStore.query(User.classType, where: User.ID.eq(id))
user.conversations to have the list of conversations loadd.
If that can not be done, next would be to get all the conversations that have a specific User.
example not working:
await Amplify.DataStore.query(UserConversation.classType
where: UserConversation.USER.eq(user.id)
)
type Message #model #auth(rules: [{allow: public}]) {
id: ID!
ConversationId: Conversation #connection
UserId: User #connection
body: String
createdDate: AWSDateTime!
}
type Conversation #model #auth(rules: [{allow: public}]) {
id: ID!
date: AWSDateTime
readBy: [ReadBy] #connection(keyName: "byConversation", fields: ["id"])
users: [UserConversation] #connection(keyName: "byConversation", fields: ["id"])
name: String
image: String
}
type ReadBy #model #auth(rules: [{allow: public}]) #key(name: "byConversation", fields: ["conversationID"]) {
id: ID!
date: AWSDateTime
RedByUsers: User #connection
conversationID: ID
}
type User #model #auth(rules: [{allow: public}]) {
id: ID!
firstName: String
lastName: String
userImg: String
createdDate: AWSDateTime
updatedDate: AWSDateTime
email: AWSEmail
conversations: [UserConversation] #connection(keyName: "byUser", fields: ["id"])
}
type UserConversation #model(queries: null) #key(name: "byUser", fields: ["userID", "conversationID"]) #key(name: "byConversation", fields: ["conversationID", "userID"]) #auth(rules: [{allow: public}, {allow: public}]) {
id: ID!
userID: ID!
conversationID: ID!
user: User! #connection(fields: ["userID"])
conversation: Conversation! #connection(fields: ["conversationID"])
}
I was able to get the second version by doing the following:
await Amplify.DataStore.query(UserConversation.classType
where: User.ID.eq(user.id)
);
The above will perform a selection of all user conversations that have the user id equal to whatever the id of the user variable is. It was a bit confusing at first as to why you need to pass the User.ID for the query, but from what I understand it is due to how the SQL query gets created by AWS DataStore, it is doing a join behind the scenes and therefore will use the column of the second table (in this case the User table) to perform the join. I wish I could point to some documentation on this, but I couldn't find any. I kinda just got lucky trying a bunch of stuff and noticing in the error message how the SQL query is generated.
I've implemented the Amplify JS Library with a Vue project and have had success with all of the features of the library except this issue. When I query a model with Elasticsearch, it returns the appropriate results, but also the error of "ResolverExecutionLimitReached".
This is the request:
let destinations = await API.graphql(graphqlOperation(queries.searchDestinations, {filter: { deviceId: { eq: params.id }}}))
This is the schema:
type Destination
#model
#searchable
#auth(rules: [{ allow: public }, { allow: private }])
#key(name: "byXpoint", fields: ["xpoint"])
#key(name: "byDevice", fields: ["deviceId"])
{
id: ID!
index: Int!
levels: [String]
name: String!
xpoint: String
sourceId: ID
Source: Source #connection
lock: Boolean
breakaway: Boolean
breakaways: String
probeId: ID!
probe: Probe #connection(fields: ["probeId"])
deviceId: ID!
device: Device #connection(fields: ["deviceId"])
orgId: ID!
org: Org #connection(fields: ["orgId"])
}
And this returns:
{
data: {
searchDestinations: {items: Array(100), nextToken: "ba1dc119-2266-4567-9b83-f7eee4961e63", total: 384}
},
errors: [
{
data: null
errorInfo: null
errorType: "ResolverExecutionLimitReached"
locations: []
message: "Resolver invocation limit reached."
path: []
}
]
}
My understanding is the AppSync API has a hard limit of returning more than 1000 entries, but this query is on a table with only ~600 entries and is only returning 384. I am executing the same command via AppSync directly via a NodeJS application and it works without issue.
Not sure where to investigate further to determine what is triggering this error. Any help or direction is greatly appreciated.
Connections in the schema were causing the single request to go beyond the 1000 request limit (exactly as stated by Mickers in the comments). Updated schema with less connections on fetch and issue was resolved.
I'm starting a new project using AWS Amplify, and have some trouble to correctly define my schema for my use case with nested objects
I have the following schema
type Company
#model
{
id: ID!
name: String!
teams: [Team] #connection (name: "CompanyTeams", sortField: "name")
}
type Team
#model
{
id: ID!
name: String!
users: [User] #connection (name: "TeamUsers", sortField: "createdAt")
company: Building #connection (name: "CompanyTeams", sortField: "name")
teamCompanyId: ID!
}
type User
#model
{
id: ID!
createdAt: String
name: String!
email: String!
team: Unit #connection (name: "TeamUsers")
}
I would like to be able to query a list of teams based on a list of companies and a user name.
For example, get all teams in companies A/B/C with user name starts with "David".
Is my current schema fine for that?
I can easily retrieve a list of teams based on the company with this kind of query
query listTeams {
listTeams(filter: {
teamCompanyId: {
eq:"A"
}
}) {
items {
name
}
}
}
But not sure how to include search on the user model. Should I override the filter and add a new custom resolver including the new filters?
Also is using filters the best solution? I believe with DynamoDB filter is only applied after we got results from the query or scan. And due to the limitation of 1mb, it might introduce a lot of reads to retrieve some results?
Happy to get any insights as I'm relatively new with AppSync / GraphQL and DynamoDB.
Thanks.
I'm having the serverless error:
Resolver associated with data sources when building from serverless.yml config file:
# serverless.yml
...
mappingTemplates:
- dataSource: Wallet
type: Query
field: walletFromId
request: "_dynamo-get-wallet.txt"
response: "_generic-result-response.txt"
- dataSource: Wallet
type: Query
field: walletsFromUser
request: "_dynamo-get-wallets-from-user.txt"
response: "_generic-result-response.txt"
- dataSource: Wallet
type: Mutation
field: registerWallet
request: "_dynamo-put-wallet.txt"
response: "_generic-result-response.txt"
dataSources:
- type: AMAZON_DYNAMODB
name: Wallet
description: 'Wallet DataSource'
config:
tableName: "${self:custom.stage}-Wallet"
serviceRoleArn: "arn:aws:iam::${self:custom.accountId}:role/${self:custom.appSync.serviceRole}"
...
I also have a schema.graphql:
type Query {
# query the wallet with given id and get the output with detail info
walletFromId(walletId: String!): Wallet!
# query wallets with given user id and get list of cards
walletsFromUser(userId: String!): [Wallet!]!
}
type Mutation {
# Add a wallet to an existing user
registerWallet(userId: String!, number: String!, cvx: String!, expirationDate: String!): Wallet!
}
type Wallet {
walletId: String!
userId: String!
number: String!
cvx: String!
expirationDate: String!
}
type Subscription {
addWallet: Wallet
#aws_subscribe(mutations: ["registerWallet"])
}
schema {
query: Query
mutation: Mutation
subscription: Subscription
}
I could not find a single clue as to what this error mean, and there isn't anything else I can get from the build logs.
This error usually means you are trying to delete a data source that is currently being used by a resolver. If you can identify the resolver pointing to the data source and delete it then you should no longer see the error message.