I am trying to create a circular reference in an amplify graphql schema.
I tried to follow the instructions on Amplify instructions.
But when I try to push, I get the following...
An error occurred during the push operation: Schema validation failed.
Directive "connection" may not be used on OBJECT.
type Item
#model
#key(name: "byParent", fields: ["id"]) {
id: ID!
subItems: [Item] #connection(keyName: "byParent", fields: ["id"])
name: String
}
What am I doing wrong?
Could you try like that ?
type Item #model
#key(name: "byParent", fields: ["parentID"]) {
id: ID!
parentID: ID
subItems: [Item] #connection(keyName: "byParent", fields: ["id"])
name: String
}
Related
am trying to persist a new node in graphql using Apollo client. This new node should attach to an existing node. Not quite sure how to go about it. Suppose I have these type definitions:
type Person{
personId: ID!
name: String!
user: User #relationship(type: "LOGS_IN_AS", direction: OUT)
}
type User{
userId: ID!
username: String!
password: String!
person: Person!
}
Now assuming I already have a person in the database as follows:
{
personId: 1,
name: "John Doe"
}
How do I mutate a corresponding User node for this Person and ensure the necessary relationship is created using Apollo's auto generated mutations? Am using a neo4j backend by the way.
Thanks in advance
Don't know how you set up neo4j database but supposedly User should have a personId to link with Person.
You should probably defined a seperate schema type called UpsertUserInput or something like below for the mutation so neo4j can use it to link with the person
type UpsertUserInput{
userId: ID!
personId: ID!
username: String!
password: String!
}
the Appollo schema is not responsible for defining where data comes from or how it's stored. It is entirely implementation-agnostic.
https://www.apollographql.com/docs/apollo-server/schema/schema/#the-schema-definition-language
I see there is a solution, just needed to look a little deeper into the auto-generated mutations in the studio. Solution along the lines of...
useMutation(CREATE_USER, {
variables:{
input:{
userName: "johndoe#example.com",
password: "jdoespassword",
person:{
connect:{
where:{
node:{
personId: 1
}
}
}
}
}
}
})
I am using amplify graphql api. Where I have an Item model with different attributes.
I am trying to create an autocomplete or autosuggest api with user-added input.
type Item #model
#searchable
{
id: ID!
name: String!
description: String
category: String
fullAddress: String!
street: String
area: String
district: String
city: String
state: String!
zip: Int!
Right now I aam querying it like
query SearchEvent {
searchEvents(filter:{
name: {
ne: $query
}
}) {
items {
id
name
}
}
}
But this gives me only full word match to a particular key, like this example is match of name.
How do I query to get a response of any match or suggestions from any key of the item object?
For example, if my item name is Laptop and api query is la it should return the laptop item and other matching items name.
Likewise, if api query is ala it should return the Alabama, Alaska names including the item name matching with ala with a limit to 10 let's say.
Anyway is this possible? Any lead will eb helpful.
I'm following a tutorial where the teacher is using a String type for his createdAt fields and suggested that if we wanted, to use a custom scalar type for a stronger typed DateTime field so I'm trying to do just that.
I'm getting the following error: Error: Unknown type "GraphQLDateTime".
Here is the offending code:
const { gql } = require('apollo-server')
const { GraphQLDateTime } = require('graphql-iso-date')
module.exports = gql`
type Post {
id: ID!
username: String!
body: String!
createdAt: GraphQLDateTime!
}
type User {
id: ID!
email: String!
token: String!
username: String!
createdAt: GraphQLDateTime!
}
input RegisterInput {
username: String!
password: String!
confirmPassword: String!
email: String!
}
type Query {
getPosts: [Post]
getPost(postId: ID!): Post
}
type Mutation {
register(registerInput: RegisterInput): User
login(username: String!, password: String!): User!
createPost(body: String!): Post!
deletePost(postId: ID!): String!
}
`
I have added the graphql-iso-date library and VSCode's intellisense is picking that up so I know that's not the issue. It's also indicating that GraphQLDateTime is not being used anywhere in the file even though I'm referencing it.
I know this is probably an easy fix but I'm still new to NodeJS and GraphQL in the context of NodeJS. Any idea what I'm doing wrong? Also is there another DateTime scalar that might be more preferable (Best practices are always a good idea.) Thanks!
There's two steps to adding a custom scalar using apollo-server or graphql-tools:
Add the scalar definition to your type definitions:
scalar DateTime
Add the actual GraphQLScalar to your resolver map:
const { GraphQLDateTime } = require('graphql-iso-date')
const resolvers = {
/* your other resolvers */
DateTime: GraphQLDateTime,
}
Note that the key in the resolver map (here I used DateTime) has to match whatever you used as the scalar name in Step 1. This will also be the name you use in your type definitions. The name itself is arbitrary, but it needs to match.
See the docs for more details.
I’m using a prisma server and graphql-yoga (graphql server on top of node.js) and I’m working for the first time with a type that has an other type as property. It’s one way so no relation I believe. In my case, a Product can be in a FavoriteList (so belong?) but a FavoriteList doesn’t have a relation the other way around.
type Product {
id: ID!
name: String!
releaseDate: DateTime!
brand: Brand!
createdAt: DateTime!
image: Image!
barcode: String
}
type FavoriteList {
id: ID!
products: [Product]
}
On my prisma admin I can add a record to FavoriteList with connecting [Product] and in the playground I can query for that by using the FavoriteLists query. But when I create a query (and resolver) for my graphql-yoga server, products are resolving as null. The query I’m using:
# prisma server & graphql server
query favoriteList {
favoriteLists {
id
products {
id
name
}
}
}
My setup for the graphql-server
type Query {
// ... other queries
favoriteLists: [FavoriteList]
}
// resovler in Query.js
async favoriteLists(root, args, context, info) {
return context.prisma.favoriteLists({}, info)
},
So having the same query, I am wondering if I have to do something else in my graphql-server? From what I can see the Product is not resolving on the FavoriteList type. Thanks in advance.
I would disagree and say you should have a relationship between Product and FavouriteList. When you break it down, one Product "belongs to" one or many FavouriteList and one FavouriteList "has" many Product. So I'd define your datamodel like this:
type Product {
id: ID!
name: String!
releaseDate: DateTime!
brand: Brand!
createdAt: DateTime!
image: Image!
barcode: String
favouriteLists: [FavouriteList!]! #relation(name: "ProductToFavouriteList")
}
type FavoriteList {
id: ID!
products: [Product!]! #relation(name: "ProductToFavouriteList")
}
Your query and resolvers look ok except maybe your resolver should return context.prisma.query.favoriteLists({}, info)?
This past year I converted an application to use Graphql. Its been great so far, during the conversion I essentially ported all my services that backed my REST endpoints to back grapqhl queries and mutations. The app is working well but would like to continue to evolve my object graph.
Lets consider I have the following relationships.
User -> Team -> Boards -> Lists -> Cards -> Comments
I currently have two different nested schema: User -> team:
type User {
id: ID!
email: String!
role: String!
name: String!
resetPasswordToken: String
team: Team!
lastActiveAt: Date
}
type Team {
id: ID!
inviteToken: String!
owner: String!
name: String!
archived: Boolean!
members: [String]
}
Then I have Boards -> Lists -> Cards -> Comments
type Board {
id: ID!
name: String!
teamId: String!
lists: [List]
createdAt: Date
updatedAt: Date
}
type List {
id: ID!
name: String!
order: Int!
description: String
backgroundColor: String
cardColor: String
archived: Boolean
boardId: String!
ownerId: String!
teamId: String!
cards: [Card]
}
type Card {
id: ID!
text: String!
order: Int
groupCards: [Card]
type: String
backgroundColor: String
votes: [String]
boardId: String
listId: String
ownerId: String
teamId: String!
comments: [Comment]
createdAt: Date
updatedAt: Date
}
type Comment {
id: ID!
text: String!
archived: Boolean
boardId: String!
ownerId: String
teamId: String!
cardId: String!
createdAt: Date
updatedAt: Date
}
Which works great. But I'm curious how nested I can truly make my schema. If I added the rest to make the graph complete:
type Team {
id: ID!
inviteToken: String!
owner: String!
name: String!
archived: Boolean!
members: [String]
**boards: [Board]**
}
This would achieve a much much deeper graph. However I worried how much complicated mutations would be. Specifically for the board schema downwards I need to publish subscription updates for all actions. Which if I add a comment, publish the entire board update is incredibly inefficient. While built a subscription logic for each create/update of every nested schema seems like a ton of code to achieve something simple.
Any thoughts on what the right depth is in object graphs? With keeping in mind the every object beside a user needs to be broadcast to multiple users.
Thanks
GraphQL's purpose is to avoid a couple of queries, so I'm sure that making the nested structure is the right way. With security in mind, add some GraphQL depth limit libraries.
GraphQL style guides suggest you have all complex structures in separate Object Types ( as you have, Comment, Team, Board... ).
Then making a complex query/mutation is up to you.
I'd like you to expand this sentence
Which if I add a comment, publish the entire board update is
incredibly inefficient
I'm not sure about this as you have your id of the Card. So adding new comment will trigger mutation which will create new Comment record and update Card with the new comment.
So your structure of data on the backend will define the way you fetch it but not so much the way you mutate it.
Take a look at the GitHub GraphQL API for example:
each of the mutations is a small function for updating/creating piece of the complex tree even if they have nested structure of types on the backend.
In addition for general knowledge of what are approaches for designing the mutations, I'd suggest this article.
You can use nesting in GraphQL like
type NestedObject {
title: String
content: String
}
type MainObject {
id: ID!
myObject: [NestedObject]
}
In the above code, the type definition of NestObject gets injected into the myObject array. To understand better you can see it as:
type MainObject {
id: ID!
myobject: [
{
title: String
content: String
}
]
}
I Hope this solves your problem!