Entity Association syntax issue with graphql queries - graphql

I am trying to understand graphql's query and mutation syntax. Given this example:
type Author {
id: Int!
firstName: String
lastName: String
posts: [Post]
}
type Post {
id: Int!
title: String
author: Author
votes: Int
}
type Query {
posts: [Post]
author(id: Int!): Author
}
What should the queries look like to associate a post with the author? Is this where connections come into play or is that something else? Here is my attempt at trying to solve the problem but to avail.
mutation createAuthor {
createAuthor(input: {
id: 123
firstName: "Bob"
lastName: "Smith"
}) {
id
firstName
lastName
}
}
query listAuthors {
listAuthors {
items {
id
firstName
lastName
}
}
}
mutation createPost {
createPost(input: {
id: 12345
title: "Title"
votes: 345
author: {
lastName: {
contains: "Bob"
}
}
}) {
id
title
votes
author {
id
firstName
lastName
}
}
}
Any help on this would be appreciated. My Goal is to Query an author and return all of the post's associated with that author as well as create a Post Mutation that adds a post to an author.

There are 2 questions in one, so I'll answer in the order there were asked.
1. return all of the posts associated with an author
Your schema looks correct. The query would look like:
query {
author(id: 1) {
id
posts {
id
title
}
}
}
2. create Post and attach to an author
In your example if you want to expose an interface to create a Post, then you would have to expose a mutation field in your schema
e.g:
type Mutation {
createPost(input: CreatePostInput): Post
}
if you want at the same time of creating a post, to also attach it to an author then you could add the authorId as part of the input, here we only want to attach the Post to an existing Author:
input CreatePostInput {
title: String
authorId: ID!
votes: Int
}
of course this is only the interface definition. We need to actually create the Post and link it to the Author inside the resolver.
The mutation query will look like:
mutation createPost {
createPost(input: {
title: "Title"
votes: 345
authorId: "authorId1"
}) {
id
title
votes
author {
id
firstName
lastName
}
}
}
Hope that helps!

Related

Spring GraphQLmultiple schemas with Query per file

with Spring-GraphQl if I have following two schemas in the resources/graphql folder:
schema1:
type Query {
bookById(id: ID): Book
}
type Book {
id: ID
name: String
pageCount: Int
author: Author
}
type Author {
id: ID
firstName: String
lastName: String
}
schema2:
type Query {
personByName(name: String): Person
}
type Person {
id: ID
firstName: String
lastName: String
}
Spring-GraphQL seems to be merging them into one GraphQL schema file and starting of Spring-Boot Graphql app ends with following error:
Caused by: graphql.schema.idl.errors.SchemaProblem: errors=['Query' type [#1:1] tried to redefine existing 'Query' type [#1:1]]
When I change it to:
schema1:
type Query {
bookById(id: ID): Book
personByName(name: String): Person
}
schema2:
type Book {
id: ID
name: String
pageCount: Int
author: Author
}
type Author {
id: ID
firstName: String
lastName: String
}
type Person {
id: ID
firstName: String
lastName: String
}
it works perfectly good and I am able to call both queries with graphiql. How graphql spring works with multiple schemas? It seems spring-graphql merges files into one schema so multiple Query types per file breaks the app.
Thanks for answer.
Spring GraphQL is loading all schema resources under the configured location and is using TypeDefinitionRegistry::merge to create a single schema out of them.
I think that redifining any type (even the Query one) should raise an error, otherwise this could hide important issues and conflicting schema definitions. That's what GraphQL Java's TypeDefinitionRegistry is doing.
You can organize your schema files like this:
graphql/schema.graphqls
type Query {
}
// add common directives, scalars, etc
graphql/books.graphqls
extend type Query {
bookById(id: ID): Book
}
type Book {
id: ID
name: String
pageCount: Int
author: Author
}
type Author {
id: ID
firstName: String
lastName: String
}
graphql/person.graphqls
extend type Query {
personByName(name: String): Person
}
type Person {
id: ID
firstName: String
lastName: String
}

Querying Many-To-Many Relationships in AWS Amplify

I have two models in my graphql schema and the one I am trying to query on, Sessions, has two #belongsTo directives (read on a forum this matters). I can successfully save these models and view them on the AWS AppSync Queries Tab where I can query getSessions successfully BUT when I try to the exact same query locally following these docs:
(https://docs.amplify.aws/lib/graphqlapi/advanced-workflows/q/platform/flutter/#combining-multiple-operations)
I get an error locally:
type "Null" is not a subtype of type 'string'
What am I doing wrong and how do I fix this so I can successfully retrieve my nested query:
Here are my models as a reference:
Sessions:
type Session
#model
#auth(
rules: [
{ allow: public }
{ allow: owner }
{ allow: groups, groups: ["Admin"] }
]
) {
id: ID!
name: String
numPeoplePresent: Int
notes: String
eIdReader: String
weighTiming: String
cows: [Cow] #manyToMany(relationName: "CowSession")
proceduresID: ID
procedures: Procedures #hasOne(fields: ["proceduresID"])
}
Cow:
type Cow
#model
#auth(
rules: [
{ allow: public }
{ allow: owner }
{ allow: groups, groups: ["Admin"] }
]
) {
id: ID!
name: String!
RfId: String
weight: [Float!]!
temperament: [Int]
breed: String
type: String
dateOfBirth: AWSDate
sessions: [Session] #manyToMany(relationName: "CowSession")
procedures: [Procedures] #manyToMany(relationName: "CowProcedures")
}
This is the query that is causing the error:
const getSession = 'getSession';
String graphQLDocument = '''query getSession(\$id: ID!) {
$getSession(id: \$id) {
numPeoplePresent
notes
name
eIdReader
id
owner
proceduresID
updatedAt
weighTiming
cows {
items {
cow {
RfId
}
}
}
}
}''';
final getSessionRequest = GraphQLRequest<Session>(
document: graphQLDocument,
modelType: Session.classType,
variables: <String, String>{'id': sessID}, //parameter of the current session can hardcode to whatever you need here
decodePath: getSession,
);
final response =
await Amplify.API.query(request: getSessionRequest).response;
print('Response: ${response.data}');
The wonderful people at amplify answered this quickly so I will relay the information here:
the problem was the intermediary ids were not included in my local query so it was unable to retrieve the nested Cows. Updated query looks like this:
getSession = 'getSession';
String graphQLDocument = '''query getSession(\$id: ID!) {
$getSession(id: \$id) {
numPeoplePresent
notes
name
eIdReader
id
owner
proceduresID
updatedAt
weighTiming
cows {
items {
id <-- needed this one
cow {
id <-- and this id too
RfId
breed
dateOfBirth
name
type
weight
}
}
}
}
}''';

Graphql: User Error: expected iterable, but did not find one for field XXX

This is movie schema:
type Book {
id: ID!
title: String
author: [Author] #belongsTo(relation: "author")
}
This is how I related book and author
public function author()
{
return $this->belongsTo('App\Models\Author', 'id', 'book_id');
}
This is schema for author
type Author {
id: ID!
title: String!
book_id: Int!
}
This is my query for Book:
extend type Query {
bookCriteria(
orderBy: _ #orderBy
where: _ #whereConditions
): [Book!]! #paginate
}
This is how I query:
{
bookCriteria
(
first: 1, page: 1
)
{
data
{
id
uuid
author
{
id
title
}
}
}
}
Finally, this is what I get as error message:
"User Error: expected iterable, but did not find one for field Book.author."
If I use hasMany instead of belongsTo, it works fine.
Please let me know what is wrong here?
Your type should be
type Book {
id: ID!
title: String
author: Author #belongsTo(relation: "author")
}

Indexing List Type field in a GraphQL type from within a Query

Say I have the following GraphQL Schema
query {
allAuthors: [Author]
}
type Author {
id: ID!
name: String!
books: [Book]
}
type Book {
id: ID!
name: String!
author: Author!
}
Now I can successfully run the following query to get all the authors and their associated books
query {
allAuthors {
name,
books {
name
}
}
}
However, if I only want to get the first three books for all authors, how would I go about doing something like that? Can we index the books field in the Author type from within a query? If so, how?
I tried something like this and it doesn't work
query {
allAuthors {
name,
books[3] {
name
}
}
}
GraphQL doesn't have syntax for this.
You can add a "limit" parameter to a field, and this is common enough:
type Query {
allAuthors(limit: Int, offset: Int): [Author!]!
}
type Author {
id: ID!
name: String!
books(limit: Int, offset: Int): [Book!]!
}
If you add parameters like this to the schema, then the query you want (for all authors, get the first three books) could look like
{
allAuthors {
name
books(limit: 3) {
name
}
}
}

Query elements where relationship is null

If I have a simple schema like:
type Author #model {
id: ID! #isUnique
posts: [Post!]! #relation(name: "AuthorOfPost")
}
type Post #model {
id: ID! #isUnique
author: Author #relation(name: "AuthorOfPost")
}
How can I query all Posts that do not have an author?
Unfortunately, I cannot find something in the authorFilter like id_is_null.
try this!
query PostsWithAuthor {
allPosts(filter: { author: null }) {
id
author {
id
}
}
}

Resources