Amplify #hasMany relationship return null - amazon-web-services

This are my first question here.
I have this schema on amplify
type Products #model {
id: ID!
title: String!
description: String!
variations: [Variation] #hasMany(indexName: "byProduct", fields: ["id"])
}
type Variation #model {
id: ID!
productId: ID! #index(name: "byProduct")
name: String!
image: String!
quantity: Int!
}
When I test the query on AppSync this return the variations, but when I use
const result = (await API.graphql(graphqlOperation(gql.listProducts))).data.listProducts.items;
or with DataStore like this
await DataStore.query(Products)
return a null or empty
variations: { nextToken: null, startedAt: null },
Someone with the same issue ? or maybe I was missing something?
thanks

Please check type of Products in local when await DataStore.query(Products)
and value of listProducts in gql when API.graphql.
I think you are missing a few fields.

Related

Not being able to edit my Many-To-Many entity in AWS AppSync

When creating a Many-to-Many relationship using GraphQL for the schema, I have been unable to alter the entity created. The #manyToMany annotation enables the syntax to produce a table named "OrderUsers". But the problem lies in my inability to alter the "OrderUsers" entity. After different attempts at changing the table, I have been unable to figure out how to change it. The only attributes that are taken into the "OrderUsers" table are the id from both the User as well as Order table, which also creates only two GSIs. Also, this is using the v2 docs.
type User #model {
id: ID!
fName: String!
lName: String!
phoneNumber: String!
email: String!
DOB: String!
orders: [Order] #manyToMany(relationName: "OrderUsers")
ordersByDate: [Order] #hasMany(indexName: "byOrderByDate", fields: ["id"])
ordersByStatusDate: [Order] #hasMany(indexName: "byOrderStatusByDate", fields: ["id"])
}
type Order #model {
id: ID!
userId: ID! #index(name: "byOrderStatusByDate", sortKeyFields: ["status", "date"]) #index(name: "byOrderByDate", sortKeyFields: ["date"])
status: String!
amount: Int
date: String!
users: [User] #manyToMany(relationName: "OrderUsers") # Test to see if I can tinker w/ the 'OrderUsers' tbl
productId: ID! #index(name: "byProductOrder", sortKeyFields: ["id"])
clubId: ID! #index(name: "byClub", sortKeyFields: ["id"])
}
After reviewing the AWS Amplify as well as AppSync docs, attempting to add GSIs to the 'OrderUsers' table, switch the partition key used from the 'User' entity to a composite partition key for the 'OrderUsers' table, and adding other attributes to the 'OrderUsers' table, everything gets wiped as I try to push/pull it. Since the syntax isn't stored in the schema.graphql file, I have been stuck. My expectation was that it would save into the schema and update the resolvers used for the mutation(s) & queries, but that has not been the case.
Any and all help would be appreciated,
Thank you & Happy holidays

Apollo federation entity union / extending entities in same subgraph

I am currently sucessfully being able to extend types across services.
Service A:
type User #key(fields: "id") {
id: ID!
}
Service B:
extend type User #key(fields: "id") {
id: ID! #external
extendedList: [ExtendedType]
}
And then ofcource resolve this just fine. However I have one case where I want to do this within one subgraph, is this possible? I know the real solution would be to split those up into two subgraphs but this is not possible currently.
I have the following entities within one subgraph:
type Chat #key(fields: "id") {
id: ID!
listingId: String!
createdAt: DateTime!
updatedAt: DateTime!
participants: [Participant!]!
title: String!
}
type Message {
id: ID!
chatId: String!
content: String!
createdAt: DateTime!
participant: Participant!
}
I dont always want to resolve messages when querying the Chat entity, and would like to do like I did in the example above and extend the type like such:
extend type Chat #key(fields: "id") {
id: ID!
messages: [Message!]!
}
Is this possible in any way when the entities are in the same subgraph?

#connection must be on an #model object type field

I have a small graphQL structure like this for AWS but when I try to push it throws me an error saying
✖ An error occurred when pushing the resources to the cloud
#connection must be on an #model object type field.
Please help to understand where I am making mistakes.
Is there any VS code extension to debug this?
type Store {
id: ID!
products: [Product] #connection(name: "StoreProducts")
}
type Product #model #searchable {
id: ID!
name: String!
description: String!
price: Float!
isOnCourse: Boolean!
isOnOutlet: Boolean!
store: Store #connection(name: "StoreProducts", sortField: "crearedAt")
file: S3Object!
}
type S3Object {
bucket: String!
region: String!
key: String!
}
type User
#model(
queries: { get: "getUser" }
mutations: { create: "registredUser", update: "updateUser" }
subscriptions: null
) {
id: ID!
username: String!
email: String!
phoneNumber: String!
registred: Boolean
orders: [Order] #connection(name: "UserOrders", sortField: "createdAt")
}
type Order
#model(
queries: null
mutations: { create: "createOrder" }
subscriptions: null
) {
id: ID!
product: Product #connection
user: User #connection(name: "UserOrders")
orderLocation: OrderLocation
crearedAt: String
}
type OrderLocation {
tableNumber: String
qrData: String
holeNumber: String
}
When you create a relation on type Product
store: Store #connection(name: "StoreProducts", sortField: "crearedAt")
You have to tell server how to look for the items. by which field name. That is why you are getting this error "#connection must be on an #model object type field."
Solution would be add fields. On type Product if you want to bring Store Products, you need to add "id" fields.
store: Store #connection(name: "StoreProducts", fields:["id"] sortField: "crearedAt")
In all other types if you want to have relation, you have to define a convenient field to query the data.

How to sort and filter by createdAt and updatedAt in aws AppSync?

I used AWS Amplify to create an GraphQL API. In DynamoDB the fields createdAt and updatedAt are created automatically. I have no way of filter values for this fields with Appsync. I would like to query data with appsync with filter range between two createdAt field but it doesn't appear in my appsync query schema.
So how can I do a query with createdAt filter or sort?
This is an AWS-Amplify specific question. It's not about how to do this with generic GraphQL.
I found the solution finally.
You have to add auto generated fields "createdAt" and "updatedAt" directly on the schema.graphql
Like that:
According to this inital schema.graphql:
type User #model(timestamps: { createdAt: "createdOn", updatedAt: "updatedOn" })
{
id: String!
username: String!
firstName: String!
lastName: String!
}
It will become:
type User #model
{
id: String!
username: String!
firstName: String!
lastName: String!
createdAt: AWSDateTime! #important to keep it to have filter with keys
updatedAt: AWSDateTime! #important to keep it to have filter with keys
}
After the amplify push, we can get items by date directly, simply like that:
query MyQuery {
listUsers(filter: {updatedAt: {between: ["2021-04-29T16:02:21.285Z", "2021-05-29T16:02:21.285Z"]}}) {
items {
id
lastName
}
}
}

AWS amplify Graph QL filter by book title and author name

AWS amplify DynamoDB Graph QL filter by book title and author name
i want to search books by book title and author name but my schema allow me to search books by book title and author ID not author name how i can achieve this.
following is my graph ql schema
type Author
#model(subscriptions: null)
#auth(
rules: [
# allow admins to create, update and delete books
{ allow: groups, groups: ["owner"] }
# allow all authenticated users to view books
{ allow: private, operations: [read] }
]
)
#key(name: "authorByCreatedAt", fields: ["isDeleted", "createdAt"], queryField: "authorByCreatedAt")
{
id: ID!
name: String!
description: String!
status : Boolean!
createdAt: String!
image: String!
isDeleted: Int!
books: [Book] #connection(keyName: "byAuthor", fields: ["id"])
}
type Book
#model(subscriptions: null)
#auth(
rules: [
# allow admins to create, update and delete books
{ allow: groups, groups: ["owner"] }
# allow all authenticated users to view books
{ allow: private, operations: [read] }
]
)
#key(name: "bookByCreatedAt", fields: ["isDeleted", "createdAt"], queryField: "bookByCreatedAt")
#key(name: "byAuthor", fields: ["authorId"])
{
id: ID!
title: String!
description: String!
image: String!
age: Int!
region: String!
isbn: String
narrator: String
status : Boolean!
createdAt: String!
isDeleted: Int!
book: String!
bookType: BookType!
authorId: ID!
authors: Author #connection(fields: ["authorId"])
}
enum BookType {
AUDIO
EPUB
}
If you are coming from the world of relational databases, this might seem like it should be trivial. In the world of DynamoDB it is more complex. You cannot create a #key that is linked to a #connection ( as far as I understand ). Some solutions to this problem:
1: Add Author's Name to Book
The author's name doesn't change typically, so you could do the below. Duplicating data is not frowned upon in DynamoDB/NoSQL world. This will give you a faster query as well.
type Book
#model(subscriptions: null)
#key(name: "BooksByAuthorName", fields: ["authorName"], queryField: "getBooksByAuthorName")
{
id: ID!
title: String!
description: String!
image: String!
age: Int!
region: String!
isbn: String
narrator: String
status : Boolean!
createdAt: String!
isDeleted: Int!
book: String!
bookType: BookType!
authorId: ID!
authorName: String
authors: Author #connection(fields: ["authorId"])
}
2: Custom Resolvers
Custom resolvers, like #function ( Lambda functions ), or the more complex custom resolver templates can be used for multiple searches, and custom logic, though I would suggest option 1 first.
3: Exploring #searchable directive
See this for more info