AWS amplify Graph QL filter by book title and author name - amazon-web-services

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

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

Amplify Graphql schema problems

I have issues when creating a schema for Amplify/graphql. I have one type called Employee and one type called Station. An Employee can work on multiple stations and vice versa. Which alternative do you think I should choose?
Here I simply look for the station ids and create an array as station ids. No real connection.
type Station #model #auth(rules: [{ allow: public }]) {
stationName: String!
id: ID
}
type Employee #model #auth(rules: [{ allow: public }]) {
id: ID
employeeName: String!
stationIds: [String]
}
I tried this but had problems register the stations field in Employees. Tried some custom inputs but I am not sure how to do it.
type Station #model #auth(rules: [{ allow: public }]) {
stationName: String!
id: ID
}
type Employee #model #auth(rules: [{ allow: public }]) {
id: ID
employeeName: String!
stations: [Station]
}
My current solution but I don't know if its overkill?
type Station #model #auth(rules: [{ allow: public }]) {
stationName: String!
id: ID
employees: [Employee] #manyToMany(relationName: "StationEmployee")
}
type Employee #model #auth(rules: [{ allow: public }]) {
id: ID
employeeName: String!
stations: [Station] #manyToMany(relationName: "StationEmployee")
}
Your current solution (3) appears to be correct based on the Amplify documentation
I'd also recommend making the ID non-nullable for both types, i.e. 'ID!'
In your first solution you used a SQL-like pattern by referring to IDs instead of types, stationIds: [String] is a counter-pattern in GraphQL since you require multiple queries to get all the results you wanted and you'd have to stitch them together by yourself.

Amplify #hasMany relationship return null

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.

#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.

On AppSync, how to query a model sort by many to many relation?

I have this schema :
type Brand #model
#key(name: "ByName", fields: ["name"])
#searchable
{
id: ID!
name: String!
link: String
image: String
bio: String
votes: [Vote] #connection(keyName: "byBrand", fields: ["id"])
}
type Vote #model
#key(name: "byUser", fields: ["userID"]) ## BelongsTo User. Index by userId
#key(name: "byBrand", fields: ["brandID", "userID"], queryField: "voteByBrand")
#searchable
{
id: ID!
userID: String!
userPhone: String!
brandID: ID!
# productTypeID: ID!
image: String
comment: String
# BelongTo User
user: User! #connection(fields: ["userID"])
# BelongTo Brand
brand: Brand! #connection(fields: ["brandID"])
}
I want to query all Brand and sort by Brand which have the most votes.
Brand 1 -> 20 votes ; Brand 2 -> 15 votes ; Brand 3 -> 8 votes ; Brand 4 -> 5 votes ;
On appSync, it seems not possible. Can you help me for that?