I'm new to GraphQL. I started with the Javascript Apollo library and cannot get a resolver to fire. It's hard for me to tell when resolvers should be called, and what key I should put.
Here's my schema and resolvers:
// The GraphQL schema in string form
const typeDefs = `
type Query { user(id: ID!): User, posts: Post }
type User { id: ID!, created: Int, username: String, bio: String, status: String, avatar: String, posts: [Post] }
type Post { id: ID!, created: Int, user_id: Int, text: String, object_set_id: Int, edited: Int, views: Int, upvotes: Int, downvotes: Int, Parent: Int }
`;
// The resolvers
const resolvers = {
Query: {
user: (parent, args, context, info) => {
return users.find(user => user.id === Number(args.id));
},
// posts: () => posts,
},
Post: {
id: (parent, args, context, info) => {
console.log(posts.filter(post => post.user_id === Number(parent.id)))
return posts.filter(post => post.user_id === Number(parent.id))
}
}
};
I want to specify a user by their user ID, then filter down to get all the posts that user has made (eventually with a time filter).
I've tried several things, but 'posts' under a user always comes up 'null'. What am I missing? Thanks.
User (Or more semantic: userById) query
Your first query works fine.
You should also add some data(Otherwise you get an error "message": "users is not defined",).
Execute query:
query{
user(id: 1){
id
username
}
}
Basic code example:
const { ApolloServer, gql } = require("apollo-server");
const users = [
{
id: 1,
username: "Kate Chopin"
},
{
id: 2,
username: "Paul Auster"
}
];
// The GraphQL schema in string form
const typeDefs = gql`
type Query {
userById(id: ID!): User
}
type User {
id: ID!
username: String
}
`;
// The resolvers
const resolvers = {
Query: {
userById: (parent, args, context, info) => {
return users.find((user) => user.id === Number(args.id));
}
}
};
const server = new ApolloServer({
typeDefs,
resolvers
});
server.listen().then(({ url }) => {
console.log(`🚀 Server ready at ${url}`);
});
posts query (Or more semantic: postById):
About posts - your query is posts and no resolver match + looks like you do a little "salad" their.
It is better to follow this example (Same idea only books/authors instead of posts/user):
https://www.apollographql.com/docs/apollo-server/getting-started/
Next, read this Resolver chains: https://www.apollographql.com/docs/apollo-server/data/resolvers/#resolver-chains
Again hello world example
const posts = [
{
id: 1,
name: "Article One"
},
{
id: 2,
name: "Article Two"
}
];
const users = [
{
id: 1,
username: "Kate Chopin",
posts: posts
},
{
id: 2,
username: "Paul Auster"
}
];
// The GraphQL schema in string form
const typeDefs = gql`
type Query {
userById(id: ID!): User
}
type User {
id: ID!
username: String
posts: [Post]
}
type Post {
id: ID!
name: String
}
`;
// The resolvers
const resolvers = {
Query: {
userById: (parent, args, context, info) => {
return users.find((user) => user.id === Number(args.id));
}
}
};
const server = new ApolloServer({
typeDefs,
resolvers
});
server.listen().then(({ url }) => {
console.log(`🚀 Server ready at ${url}`);
});
Query:
Related
I would like to inherit resolvers from a graphql interface.
Consider this schema.
const typeDefs = gql`
interface Name {
name: String!
surname: String!
}
type Person implements Name {
_id: ID!
name: String!
surname: String!
}
type Query {
getPerson: Person!
}
}
And these resolvers:
const queryResolver = {
Name: {
name: () => "John",
surname: () => "Doe"
},
Query: {
getPerson: async (parent, args, context, info) => {
return {
_id: "1",
};
},
}
}
This is my server
const { ApolloServer } = require("apollo-server");
const typeDefs = require("./types");
const queryResolvers = require("./resolvers/query");
const resolvers = {
Query: queryResolvers.Query,
Name: queryResolvers.Name,
};
try {
const server = new ApolloServer({
typeDefs,
resolvers,
});
server.listen().then(({ url }) => {
console.log(`Apollo server listening on ${url}`);
});
} catch (e) {
console.error(e);
}
I would like that when querying the server
query Query {
getPerson {
name
surname
}
}
I get John Doe, as I would expect that Person inherits the resolvers from Name.
On ApolloServer v.2 I get this functionality implemented through inheritResolversFromInterfaces https://www.apollographql.com/docs/apollo-server/v2/api/graphql-tools/
I have not been able to find and equivalent on ApolloServer v3.0
The only option I could find is by creating the schema by using makeExecutableSchema from the #graphql-tools/schema, and then passing that schema to the ApolloServer constructor:
const schema = makeExecutableSchema({
typeDefs,
resolvers,
inheritResolversFromInterfaces: true,
});
const server = new ApolloServer({
...otherApolloArguments,
schema,
});
const { ApolloServer, gql } = require('apollo-server-express');
const express = require('express');
const port = process.env.PORT || 4000;
const notes = [
{ id: '1', content: 'This is a note', author: 'Adam Scott' },
{ id: '2', content: 'This is another note', author: 'Harlow Everly' },
{ id: '3', content: 'Oh hey look, another note!', author: 'Riley Harrison' }
];
const typeDefs = gql `
type Note {
id: ID
content: String
author: String
}
type Query {
hello: String
notes: [Note]
note(id: ID!): Note
}
type Mutation {
newNote(content: String!): Note
}
`;
const resolvers = {
Query:{
hello: () => 'Hello World',
notes: () => notes,
note: (parent, args) => {
return notes.find(note => note.id == args.id);
},
Mutation: {
newNote: (parent, args) => {
let noteValue = {
id : String(notes.length + 1),
content : args.content,
author: 'Adam Scott',
};
notes.push(noteValue);
return noteValue;
}
}
},
}
Some people had naming issues but seems that I'm using the same in resolver as well as in schema.
Please bare with me, this is my second day in GraphQL and Express. I removed intentionally imports and assignment of express object, middleware since it does not let me post.
I think you are simply missing a curly bracket.
const resolvers = {
Query:{
hello: () => 'Hello World',
notes: () => notes,
note: (parent, args) => {
return notes.find(note => note.id == args.id);
}
}, <==== THIS IS MISSING =====>
Mutation: {
newNote: (parent, args) => {
let noteValue = {
id : String(notes.length + 1),
content : args.content,
author: 'Adam Scott',
};
notes.push(noteValue);
return noteValue;
}
}
I'm trying to push data to a nested array in mongodb. I'm using mongoose as well.
This is just mock code to see if i can get it working:
User model:
import mongoose from "mongoose";
const CoinSchema = new mongoose.Schema({
coinID: { type: String },
});
const CoinsSchema = new mongoose.Schema({
coin: [CoinSchema],
});
const WatchlistSchema = new mongoose.Schema({
watchlistName: { type: String },
coins: [CoinsSchema],
});
const NameSchema = new mongoose.Schema({
firstName: { type: String },
lastName: { type: String },
username: { type: String },
});
const UserSchema = new mongoose.Schema({
name: [NameSchema],
watchlists: [WatchlistSchema],
test: String,
});
const User = mongoose.model("User", UserSchema);
export default User;
route:
fastify.put("/:id", async (request, reply) => {
try {
const { id } = request.params;
const newCoin = request.body;
const updatedUser = await User.findByIdAndUpdate(id, {
$push: { "watchlists[0].coins[0].coin": newCoin },
});
await updatedUser.save();
// console.dir(updatedUser, { depth: null });
reply.status(201).send(updatedUser);
} catch (error) {
reply.status(500).send("could not add to list");
}
});
request.body // "coinID": "test"
I've tried a lot of different ways to push this data but still no luck. I still get 201 status codes in my terminal which indicates something has been pushed to the DB, but when I check nothing new is there.
Whats the correct way to target nested arrays and push data to them?
It's not perfect but you could get the user document, update the user's watchlist, and then save the updated watchlist like so:
fastify.put("/:id", async (request, reply) => {
try {
const { id } = request.params;
const newCoin = request.body;
// get the user
let user = await User.findById(id);
// push the new coin to the User's watchlist
user.watchlists[0].coins[0].coin.push(newCoin);
//update the user document
const updatedUser = await User.findOneAndUpdate({ _id: id },
{
watchlists: user.watchlists,
},
{
new: true,
useFindAndModify: false
}
);
reply.status(201).send(updatedUser);
} catch (error) {
reply.status(500).send("could not add to list");
}
});
I'm trying to make a findOneByEmail/id for graphQL. I saw a couple of questions, blog posts, and videos, but they didn't help my case. I know I have to add a filter, but I have to be missing something
Here are my resolvers
const users = [
{id: 1, email:'a#a.a',password:'zaq1#WSX', pons:[{value:'test'}]},
{id: 2, email:'b#b.b',password:'ZAQ!2wsx', pons:[{value:'tset'}]}
];
const pons = [{value: 'test'}];
module.exports = {
Query: {
users: () => users,
pons: () => pons,
}
};
typeDefs
const {gql} = require('apollo-server-express');
module.exports = gql`
type Pon {
value: String!
}
type User {
id: Int
email: String!
password: String!
pons: [Pon]!
}
type Query {
findUser(id: Int): [User]
users: [User]
pons: [Pon]
}
`;
app.js
const express = require('express');
const { ApolloServer } = require('apollo-server-express');
const typeDefs = require('./graphql/typeDefs.js');
const resolvers = require('./graphql/resolvers.js');
const server = new ApolloServer({typeDefs, resolvers});
const app = express();
server.applyMiddleware({ app });
app.listen({ port: 4000 }, () =>
console.log(`🚀 Server ready at http://localhost:4000${server.graphqlPath}`)
);
I am using express with apollo-server-express.
I tried adding users(id: Int) and users(email: String), but with no success. You can see it in findUser query. I am calling the query like:
query{
findUser(id: 1) {
email
pons {
value
}
}
}
In the GQL playground.
I'd like to able to filter the data on the server, not on the client, and can't find the solution anywhere
You can get the id parameters in GraphQL resolver and query user by it.
E.g.
const express = require('express');
const { ApolloServer } = require('apollo-server-express');
const { gql } = require('apollo-server-express');
const users = [
{ id: 1, email: 'a#a.a', password: 'zaq1#WSX', pons: [{ value: 'test' }] },
{ id: 2, email: 'b#b.b', password: 'ZAQ!2wsx', pons: [{ value: 'tset' }] },
];
const pons = [{ value: 'test' }];
const typeDefs = gql`
type Pon {
value: String!
}
type User {
id: Int
email: String!
password: String!
pons: [Pon]!
}
type Query {
findUser(id: Int): User
users: [User]
pons: [Pon]
}
`;
const resolvers = {
Query: {
users: () => users,
pons: () => pons,
findUser: (_, { id }) => users.find((u) => u.id === id),
},
};
const server = new ApolloServer({ typeDefs, resolvers });
const app = express();
server.applyMiddleware({ app });
app.listen({ port: 4000 }, () => console.log(`🚀 Server ready at http://localhost:4000${server.graphqlPath}`));
query in GraphQL playground:
query{
findUser(id: 1){
email
pons {
value
}
}
}
response:
{
"data": {
"findUser": {
"email": "a#a.a",
"pons": [
{
"value": "test"
}
]
}
}
}
This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 3 years ago.
I need a list of files in folder, returned with GraphQL query. Can someone explain, how to configure the type and resolver the list? I have some configuration with fs() method, but it doesn't return the list of files. There's a code of schema and resolvers below. To shorten the code, I removed some resolvers that are not related to files.
Will be very grateful for any help!
schema.js
const { buildSchema } = require('graphql');
module.exports = buildSchema(`
type Hero {
_id: ID!
title: String!
description: String
date: String!
}
type File {
path: String
}
input HeroInput {
title: String!
description: String!
date: String!
}
input HeroUpdate {
_id: ID!
title: String!
description: String
date: String!
}
input HeroRemove {
_id: ID!
}
type RootQuery {
heroes: [Hero!]!
findHero(id: ID!): Hero
files: File
}
type RootMutation {
createHero(heroInput: HeroInput): Hero
deleteHero(heroRemove: HeroRemove): Hero
updateHero(heroUpdate: HeroUpdate): Hero
}
schema {
query: RootQuery
mutation: RootMutation
}
`);
resolvers.js
const Hero = require('./models/hero');
const path = require('path');
const fs = require('fs');
module.exports = {
files: () => {
const filesPath = path.join(__dirname, './files');
return fs.readdir(filesPath, function (err, files) {
if (err) {
return console.log('Unable to scan directory: ' + err);
}
console.log(files);
return files.map(file => {
return {
path: file
};
});
});
},
heroes: () => {
return Hero.find()
.then(heroes => {
return heroes.map(hero => {
return {
...hero._doc,
_id: hero.id,
date: new Date(hero.date).toISOString()
};
});
})
.catch(err => {
throw err;
});
}
};
Your files resolver does not work as expected because you are returning fs.readdir. However, the function is asynchronous and therefore immediately returns undefined instead of the result of your callback function.
To avoid this problem you could use fs.readdirSync instead of fs.readdir:
files: () => {
const filesPath = path.join(__dirname, './files');
const files = fs.readdirSync(filesPath);
return files.map(file => ({path: file}));
}
Note: I used a shorthand notation for the map function in order to immediately return the object!
Documentation of fs.readdirSync: https://nodejs.org/api/fs.html#fs_fs_readdirsync_path_options
Hope this solved your problem :)
Cheers,
derbenoo
The solution is to configure the File type and query in schema.js
const { buildSchema } = require('graphql');
module.exports = buildSchema(`
type Hero {
_id: ID!
title: String!
description: String
date: String!
}
type File {
path: String
}
input HeroInput {
title: String!
description: String!
date: String!
}
input HeroUpdate {
_id: ID!
title: String!
description: String
date: String!
}
input HeroRemove {
_id: ID!
}
type RootQuery {
heroes: [Hero!]!
findHero(id: ID!): Hero
files: [File]
}
type RootMutation {
createHero(heroInput: HeroInput): Hero
deleteHero(heroRemove: HeroRemove): Hero
updateHero(heroUpdate: HeroUpdate): Hero
}
schema {
query: RootQuery
mutation: RootMutation
}
`);