Apollo federation entity union / extending entities in same subgraph - apollo

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?

Related

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.

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

How to store multiple key values in an Array on one field

I have a football team model as seen here
type Team #model
{
id: ID!
name: String!
faId: ID!
seasonID: ID!
seasons: [seasonID] #connection(fields: ["seasonID"])
}
The team will play in multiple seasons. I would like to store the data in a array
seasonID: [ID]!
Then when fetching the data, I can return all the seasons the Team was a part of.
Is this possible with Dynamodb. When I try to say it this way it says:
InvalidDirectiveError: All fields provided to an #connection must be non-null scalar or enum fields.
InvalidDirectiveError: All fields provided to an #connection must be non-null scalar or enum fields. means that the part where you have [seasonID] should not be any of the typs ID, String, Int etc as shown & described here
The connection for cardinality One-To-Many 1..* you are trying to do there would be achieved by creating a separate model called Season. eg:
# Separate model for Season
type Season #model{
id: ID!
name: String!
}
type Team #model
{
id: ID!
name: String!
faId: ID!
seasonID: ID!
seasons: [Season] #connection(fields: ["seasonID"])
}
You can see a example of more you can do here