As a newbie to GraphQL I would appreciate some help in the following:
I have query which retrieves its author and that author's books. I would like the author's books to be author's other books, meaning - except the one being queried. What does it involve?
apollo-angular query:
const getBookQuery = gql`
query($id: ID){
book(id: $id){
id
name
year
author {
id
firstName
lastName
books { # <-- give me all _except_ the one with $id
name
year
id
}
}
}
}
`;
and in the schema.js (node.js server) I have something like:
const RootQuery = new GraphQLObjectType({
name: 'RootQueryType',
fields: {
book: {
type: BookType,
args: { id: { type: GraphQLID } },
resolve(parent, args) {
const { id } = args;
return Book.findById(id);
},
},
books: {
type: GraphQLList(BookType),
resolve() {
return Book.find({});
},
},
// ... other queries ...
}
})
The solution I am looking for should, obviously, not break other queries for books.
You should be able to achieve the exclusion by adding an argument to the Author type def and then appropriately using that argument in the resolver for books (which should be nested resolver on your Author type). Will need to adapt syntax for apollo-angular.
type Author {
id:
firstName: String
lastName: String
books(exclude: ID): [Book]
}
const resolverMap = {
Query: {
book(arent, args, ctx, info) {
...
}
},
Author: {
books(obj, args, ctx, info) {
// Use args.exclude passed to filter results
},
},
};
const getBookQuery = gql`
query($id: ID){
book(id: $id){
id
name
year
author {
id
firstName
lastName
books(exclude: $id) {
name
year
id
}
}
}
}
`;
Related
I am new to GraphQL. I have a query which updates a user by his Id. I want to return the id of the document that was updated, but it is returning:
{
"data": {
"editUser": {
"_id": null
}
}
}
GraphQL Query:
mutation {editUser(_id: "5eb801eef0171040044de79f", name: "dd", title:"teacher" , email:"dd#here.com") {
_id
}
}
shema:
const { buildSchema } = require("graphql");
const schema = buildSchema(`type Query {
getUser(_id: ID): User
getUsers: [User]
}
type User {
_id: ID
name: String
title: String
email: String
}
type Mutation {
addUser(name: String, title: String, email: String): User,
editUser(_id: ID, name: String, title: String, email: String): User,
deleteUser(_id: ID): String
}`);
module.exports = { schema };
in resolver.js:
try {
const client = await MongoClient.connect(url);
var dbo = client.db("UserApp");
const myquery = { _id: ObjectId(args._id) };
const updateduser = await dbo
.collection("users")
.updateOne(myquery, { $set: { name: args.name } });
const founduser = await dbo.collection("users").findOne(myquery);
console.log(founduser);
return founduser._id.toString();
} catch (err) {
console.log(err);
}
I have two database tables:
books: id | title | author_id
authors: id | name
typeDefs:
const typeDefs = gql`
type Author {
id: ID!
name: String!
}
type Book {
id: ID!
title: String!
author_id: String!
author: Author!
}
type Query {
book(id: ID!): Book
author(id: ID!): Author
}
`
Resolvers:
const resolvers = {
Query: {
async book(parent, args) {
const dbRes = await query('SELECT id, title, author_id FROM books WHERE id=$1', [args.id])
return dbRes[0]
},
async author(parent, args) {
const dbRes = await query('SELECT id, name FROM authors WHERE id=$1', [args.id])
return dbRes[0]
}
}
}
I can make request to get book:
const queryBook = gql`
query Book($id: ID!) {
book(id: $id) {
id
title
author_id
}
}
`
const { data } = useQuery(queryBook, { variables: { id: 1 } })
But how can i make request for book with author data based on author_id like this?
const queryBook = gql`
query Book($id: ID!) {
book(id: $id) {
id
title
author_id
author {
id
name
}
}
}
`
You should write a custom resolver for the author of a Book
const resolvers = {
Book: {
author: (parent) => {
console.log(parent.author_id)
return (from database or any where....);
},
},
.
.
.
}
i'm using apollo-server and want to learn graphql schema, queries and mutations but iam not getting correct resources for understing how mutation works and how to define mutation in resolvers
i have tried something like adding "mutation" similar to "query" in the resolvers but no use.
#schema
const typeDefs = gql`
type Book {
title: String
author: String
}
type Mutation {
addBook(title: String, author: String): Book
}
type Query {
getBooks: [Book]
}
`;
#resolvers
const resolvers = {
Query: {
getBooks: () => books
}
};
#querying in graphql playground
mutation{
addBook( title: "a sad love story",author:"pavan kalyan"){
title
author
}
}
#result i got
{
"data": {
"addBook": null
}
}
i want to get the title and author in the result same as the arguments iam passing in the query
and no error messages
You need to define the mutation in your resolvers:
const resolvers = {
Query: {
getBooks: () => books,
},
Mutation: {
addBook: (_, {input}) => {
// ... code to add book somewhere
const addedBook = insert(input.title, input.author);
return addedBook; // i.e. {title: input.title, author: input.author};
}
}
}
Suppose I have following type definition for my GraphQL API:
const typeDef = `
type Book {
title: String
author: Author
likes: Int
}
type Author {
id: String
name: String
age: Int
books: [Book]
}
type Query{
books(authorid: String!): Book
}
`
Then, how many resolvers do I need for this? Should I handle this query request with only one resolver books and return all books and author info or should I make many resolvers such as Query -> books, Book -> author and Author -> books? I am not sure how the modular schema and resolver works together.
No matter how many type(Book, Author etc) or input you use you need to provide .
const schema = `
type Mutation {
mutatePost(postId:Int) :Int
}
type Query {
hello: String
posts: [String]
books(authorId: String!): Book
}
`
You need to use same name as you defined in Query must be same in resolver
const resolvers = {
Query: {
async hello() {
return 'Hello';
},
async posts() {
return ['Hello', 'World];
},
async books(_, { authorId }) {
//Return data which you is defined in type Book
//return Book
}
},
Mutation: {
async mutatePost(_, {
postId
}, context) {
//return Integer
}
},
}
Only thing every Query and Mutation need queryResolver and mutationResolver
I'm trying to return a subscription which consists of the following:
const postsSubscription = gql`
subscription postAdded {
postAdded {
id
title
description
author{
name
}
}
}
`
What happens is that Author is type of User, and I just pass an authorId. That means that I don't have the author name when I create the Post:
createPost: async (root, req, { posts }) => {
const Item = {
id: uuid.v4(),
authorId: '565dbdc0-36f2-4bba-be67-c126d0c71fff',
...req
}
await posts.create({ Item })
pubsub.publish('postAdded', { postAdded: Item })
return Item
},
Here is the Author resolver:
Post: {
author: async({ authorId }, req, { users }) => {
const Key = { id: authorId }
const { Item } = await users.get({ Key })
return Item
}
}
Here is the schema:
type Post {
id: ID
title: String
description: String
author: User #relation(name: "PostAuthor")
}
type User {
id: ID
name: String
email: String
password: String
posts: [Post] #relation(name: "UserPosts")
}
type PostPayload {
post: Post
}
type CreateUserPayload {
user: User
}
type Query {
allPosts: [Post]
allUsers: [User]
post(id: ID!): Post
user(id: ID!): User
}
type Mutation {
createPost(input: CreatePostInput!): PostPayload
updatePost(input : UpdatePostInput!): PostPayload
createUser(input : CreateUserInput!): CreateUserPayload
}
type Subscription {
postAdded: Post
}
input CreatePostInput {
title: String!
description: String!
}
input UpdatePostInput {
id: ID!
title: String!,
description: String!
}
input CreateUserInput {
name: String!
email: String!
password: String!
}
schema {
query: Query
mutation: Mutation
subscription: Subscription
}
So, my question is, how to pass all required fields (including the connections) to the subscription?
I made it work, but not as I wanted.
1) I had to remove this part of the code:
Post: {
author: async({ authorId }, req, { users }) => {
const Key = { id: authorId }
const { Item } = await users.get({ Key })
return Item
}
}
and added this function to the createPost function itself:
createPost: async (root, { input }, { posts, users }) => {
const Key = { id: '3b1884b8-9ee7-4d9d-ab2f-ff32bcd69b9a' }
const user = await users.get({ Key })
const Item = {
id: uuid.v4(),
author: user.Item,
...input
}
await posts.create({ Item })
await pubsub.publish(POST_ADDED_TOPIC, { [POST_ADDED_TOPIC]: Item })
return { post: Item }
}
So this is kinda fixed. But, if you know how to fix this, using the first approach (Post: author thingy) I'll appreciate.