I have problem with some parts of my code:
const BookType = new GraphQLObjectType({
name: "Book",
fields: () => ({
id: {type: GraphQLID},
title: {type: GraphQLString},
author: {type: GraphQLString},
})
})
const fQuery = new GraphQLObjectType({
name: "firstQuery",
fields: {
books: {
type: new GraphQLList(BookType),
resolve(parent, args){
return Book.find({});
}
},
book: {
type: BookType,
args: {id: {type: GraphQLID}},
resolve(parent, args){
return Book.findById(args.id);
}
},
author: {
type: BookType,
args: {author: {type: GraphQLString}},
resolve(parent, args){
return ??????????
}
},
}
})
I don't know how to find book by author.
Next thing - mutations:
const Mutation = new GraphQLObjectType({
name: "Mutation",
fields: {
add: {
type: BookType,
args: {
title: {type: GraphQLString},
author: {type: GraphQLString},
},
resolve(parent,args){
let book = new Book({
title:args.title,
author:args.author,
})
return book.save()
}
},
update: {
type: BookType,
args: {
title: {type: GraphQLString},
author: {type: GraphQLString},
},
resolve(parent, args){
return Book.findByIdAndUpdate(args.id, {
title: args.title,
author: args.author
})
}
},
del: {
type: BookType,
args: {
id: {type: GraphQLID},
},
resolve(parent,args){
return Book.findByIdAndDelete(args.id)
}
}
}
});
Update does not work. Delete removes the first item, not the selected one by ID. This is my homework assignment. I've been sitting on this for a few hours now and can't seem to get it right.
Do anyone of you know how to fix this?
thanks in advance!
UPDATE: Searching by author does not work. I was able to fix the rest.
You also need an author GraphQLObjectType and if you store the id of the author in your books you can add a new field in author
EDIT: Also you can try find by name (but it must be unique or you will have conflicted results)
booksByAuthor: {
type: GraphQLList(BookType),
async resolve(parent, args) {
return Books.find( { id:parent.id } )
},
}
So will be something like
const AuthorType = new GraphQLObjectType({
name: 'Author',
fields: () => ({
id: { type: GraphQLID },
name: { type: GraphQLString },
booksByAuthor: {
type: GraphQLList(BookType),
async resolve(parent, args) {
return Books.find({ id: parent.id });
},
},
}),
});
I don't see the id as argument in your mutation. You need to pass the id.
update: {
type: BookType,
args: {
id:{type: GraphQLID}
title: {type: GraphQLString},
author: {type: GraphQLString},
},
resolve(parent, args){
return Book.findByIdAndUpdate(args.id, {
title: args.title,
author: args.author
})
}
},
I'm new to this as well but I hope it helps
Related
I am trying to add nested object data to mongodb database using graphql and also fetch the data using the code below
........................................................................................................................................................................................................
const graphql = require('graphql');
const Pricing = require('../models/pricing');
const { GraphQLObjectType, GraphQLString, GraphQLID,
GraphQLInt, GraphQLList, GraphQLNonNull, GraphQLSchema } = graphql;
const PrcingType = new GraphQLObjectType({
name:'Pricing',
fields: () => ({
monthly:{
starter: {
type: {type: GraphQLString},
},
scale: {
type: {type: GraphQLString},
price: {type: GraphQLString},
},
},
quarterly: {
starter: {
type: {type: GraphQLString},
},
scale: {
type: {type: GraphQLString},
price: {type: GraphQLString},
},
},
})
});
const RootQuery = new GraphQLObjectType({
name: 'RootQueryType',
fields: {
pricings: {
type: new GraphQLList(PrcingType),
resolve(parent, args){
return Pricing.find({});
},
},
}
});
const Mutation = new GraphQLObjectType({
name: 'Mutation',
fields: {
addPricing: {
type: PrcingType,
args: {
monthly:{
starter: {
type: {type: GraphQLString},
},
scale: {
type: {type: GraphQLString},
price: {type: GraphQLString},
},
},
quarterly: {
starter: {
type: {type: GraphQLString},
},
scale: {
type: {type: GraphQLString},
price: {type: GraphQLString},
},
},
},
resolve(parent, args){
let pricing = new Pricing({
monthly:{
starter: {
type: {type: GraphQLString},
},
scale: {
type: {type: GraphQLString},
price: {type: GraphQLString},
},
},
quarterly: {
starter: {
type: {type: GraphQLString},
},
scale: {
type: {type: GraphQLString},
price: {type: GraphQLString},
},
},
});
return pricing.save();
}
}
}
})
module.exports = new GraphQLSchema({
query: RootQuery,
mutation: Mutation
});
But when I run the grapghql server I get this error
{
"errors": [
{
"message": "The type of Pricing.monthly must be Output Type but got: undefined."
},
{
"message": "The type of Pricing.quarterly must be Output Type but got: undefined."
},
{
"message": "The type of Mutation.addPricing(monthly:) must be Input Type but got: undefined."
},
{
"message": "The type of Mutation.addPricing(quarterly:) must be Input Type but got: undefined."
}
]
}
What am I doing wrong?
I have a model defined as so:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const feedbackSchema = new Schema({
Name: {
type: String,
required: true,
},
Email: {
type: String,
required: true,
},
Project: {
type: String,
required: true,
},
Wonder: {
type: String,
required: true,
},
Share: {
type: String,
required: true,
},
Delight: {
type: String,
required: true,
},
Suggestions: {
type: String,
required: true,
},
Rating: {
type: String,
required: true,
},
dateCreated: {
type: Date,
default: Date.now(),
},
user: {
type: Schema.Types.ObjectId,
ref: 'User'
}
});
const UserSchema = new Schema({
googleId: {
type: String
},
displayName: {
type: String
},
firstName: {
type: String
},
lastName: {
type: String
},
image: {
type: String
},
createdAt: {
type: Date,
default: Date.now(),
},
feedback: [feedbackSchema],
})
module.exports = mongoose.model("User", UserSchema);
An example document:
{
_id: ObjectId('60b9dc728a516a4669b40dbc'),
createdAt: ISODate('2021-06-04T07:42:01.992Z'),
googleId: '2342987239823908423492837',
displayName: 'User Name',
firstName: 'User',
lastName: 'Name',
image: 'https://lh3.googleusercontent.com/a-/89wf323wefiuhh3f9hwerfiu23f29h34f',
feedback: [
{
dateCreated: ISODate('2021-06-04T07:42:01.988Z'),
_id: ObjectId('60b9dc858a516a4669b40dbd'),
Name: 'Joe Bloggs',
Email: 'joe#bloggs.com',
Project: 'Some Project',
Suggestions: 'Here are some suggestions',
Rating: '10'
},
{
dateCreated: ISODate('2021-06-04T08:06:44.625Z'),
_id: ObjectId('60b9df29641ab05db7aa2264'),
Name: 'Mr Bungle',
Email: 'mr#bungle',
Project: 'The Bungle Project',
Suggestions: 'Wharghable',
Rating: '8'
},
{
dateCreated: ISODate('2021-06-04T08:08:30.958Z'),
_id: ObjectId('60b9df917e85eb6066049eed'),
Name: 'Mike Patton',
Email: 'mike#patton.com',
Project: 'No More Faith',
Suggestions: 'Find the faith',
Rating: '10'
},
],
__v: 0
}
I have two routes defined, the first one is called when the user clicked a button on a feedback item on the UI which takes the user to a "are you sure you want to delete this record"-type page displaying some of the information from the selected feedback record.
A second route which, when the user clicks 'confirm' the subrecord is deleted from the document.
The problem I'm having is I can't seem to pull the feedback from the user in order to select the document by id, here's what I have so far for the confirmation route:
router.get('/delete', ensureAuth, async (req, res) => {
try {
var url = require('url');
var url_parts = url.parse(req.url, true);
var feedbackId = url_parts.query.id;
const allFeedback = await User.feedback;
const feedbackToDelete = await allFeedback.find({ _id: feedbackId });
console.log(feedbackToDelete);
res.render('delete', {
imgSrc: user.image,
displayName: user.firstName,
feedbackToDelete
});
} catch (error) {
console.log(error);
}
})
Help much appreciated
Update
You should be able to do just this:
const feedbackToDelete = await User.feedback.find({ _id: feedbackId });
Or if feedbackId is just a string, which is appears to be, you may have to do something like:
// Create an actual _id object
// That is why in your sample doc you see ObjectId('foobarbaz')
const feedbackId = new mongoose.Types.ObjectId(url_parts.query.id);
const feedbackToDelete = await User.feedback.find({ _id: feedbackId });
Original
Shouldn't this:
const allFeedback = await User.feedback; (a field)
be this:
const allFeedback = await User.feedback(); (a method/function)
?
I used mongoose and Graphql to send my queries to the database but for some reason it doesn't let me create documents. I have tried creating a new user with full admin privileges it hasn't worked I tried changing the default user password but it didn't work.
I rechecked my mongoose model no errors so what might be the problem.
FYI the problem arose with the return (author.save()) and the database connects normally
Author Model
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const authorSchema = new Schema({
name: String,
age: Number
});
module.exports = mongoose.model('Author', authorSchema);
schema.js
const graphql = require('graphql');
const Book = require('../models/book');
const Author = require('../models/Author');
const _ = require('lodash');
const {
GraphQLObjectType,
GraphQLString,
GraphQLSchema,
GraphQLID,
GraphQLInt,
GraphQLList
} = graphql;
const BookType = new GraphQLObjectType({
name: 'Book',
fields: ( ) => ({
id: { type: GraphQLID },
name: { type: GraphQLString },
genre: { type: GraphQLString },
author: {
type: AuthorType,
resolve(parent, args){
//return _.find(authors, { id: parent.authorId });
}
}
})
});
const AuthorType = new GraphQLObjectType({
name: 'Author',
fields: ( ) => ({
id: { type: GraphQLID },
name: { type: GraphQLString },
age: { type: GraphQLInt },
books: {
type: new GraphQLList(BookType),
resolve(parent, args){
//return _.filter(books, { authorId: parent.id });
}
}
})
});
const RootQuery = new GraphQLObjectType({
name: 'RootQueryType',
fields: {
book: {
type: BookType,
args: { id: { type: GraphQLID } },
resolve(parent, args){
//return _.find(books, { id: args.id });
}
},
author: {
type: AuthorType,
args: { id: { type: GraphQLID } },
resolve(parent, args){
//return _.find(authors, { id: args.id });
}
},
books: {
type: new GraphQLList(BookType),
resolve(parent, args){
//return books;
}
},
authors: {
type: new GraphQLList(AuthorType),
resolve(parent, args){
//return authors;
}
}
}
});
const Mutation = new GraphQLObjectType({
name: 'Mutation',
fields: {
addAuthor: {
type: AuthorType,
args: {
name: { type: GraphQLString },
age: { type: GraphQLInt }
},
resolve(parent, args){
let author = new Author({
name: args.name,
age: args.age
});
return (author.save())
}
}
}
});
module.exports = new GraphQLSchema({
query: RootQuery,
mutation: Mutation
})
;
error message
(node:31482) MongoError: (Unauthorized) not authorized on admin to execute command {
insert: "authors", documents: [[{name gyfdgyiszukjfheusdzyih} {age 88} {_id
ObjectID("60af9c682215ea7afad86f4c")} {__v 0}]], ordered: false, writeConcern: { w:
"majority" }
Found this issue, after trying practice by GraphQL tutorial on Youtube.
To solve it, you need to update your mongoose model to the last version.
I'm trying to separate out my types into individual files. By doing so I've found that any type definition that references the usertype I get the below error.
User:
const {
GraphQLObjectType,
GraphQLList,
GraphQLString,
GraphQLBoolean,
GraphQLID,
} = require("graphql");
const UserType = new GraphQLObjectType({
name: "User",
fields: () => ({
_id: { type: GraphQLID },
name: { type: GraphQLString },
password: { type: GraphQLString },
email: { type: GraphQLString },
active: { type: GraphQLBoolean },
emailConfirmed: { type: GraphQLBoolean },
licenses: {
type: new GraphQLList(LicenseType),
async resolve(parent, args) {
return await LicenseController.getUserLicenses({ id: parent._id });
},
},
services: {
type: new GraphQLList(ServiceType),
async resolve(parent, args) {
return await ServiceController.getUserServices({ id: parent._id });
},
},
}),
});
const LicenseType = require("../types/licenseType");
const ServiceType = require("../types/serviceType");
const LicenseController = require("../../controllers/licenseController");
const ServiceController = require("../../controllers/serviceController");
module.exports = UserType;
License:
const {
GraphQLObjectType,
GraphQLInt,
GraphQLString,
GraphQLBoolean,
GraphQLID,
} = require("graphql");
const UserType = require("../types/userType");
const UserController = require("../../controllers/userController");
const LicenseType = new GraphQLObjectType({
name: "License",
fields: () => ({
_id: { type: GraphQLID },
token: { type: GraphQLString },
creationDate: { type: GraphQLString },
expirationDate: { type: GraphQLString },
btcAddress: { type: GraphQLString },
sessions: { type: GraphQLInt },
active: { type: GraphQLBoolean },
user_id: { type: GraphQLID },
user: {
type: UserType,
async resolve(parent, args) {
return await UserController.getSingleUser({ id: parent.user_id });
},
},
}),
});
module.exports = LicenseType;
Error:
Error: One of the provided types for building the Schema is missing a name.
I've tried moving the type/controller definitions above and below the type definitions with no change. How would I provide the user data from the license type?
You can move the require calls inside the fields function -- this way they will not be evaluated until the function is actually called when your schema is constructed.
const LicenseType = new GraphQLObjectType({
name: "License",
fields: () => {
const UserType = require("../types/userType");
const UserController = require("../../controllers/userController");
return {
_id: { type: GraphQLID },
token: { type: GraphQLString },
creationDate: { type: GraphQLString },
expirationDate: { type: GraphQLString },
btcAddress: { type: GraphQLString },
sessions: { type: GraphQLInt },
active: { type: GraphQLBoolean },
user_id: { type: GraphQLID },
user: {
type: UserType,
async resolve(parent, args) {
return await UserController.getSingleUser({ id: parent.user_id });
},
},
}
},
});
I am currently building mern + graphql app. I am new to graphql and I have two different models a User Model and Character model. The Character Model is nested in the User. When I create a user in the Graphiql interface I want it to display its data and the character that is associated with the specific user but instead it is displaying every character that has been created in the database and adding them to every user created instead of the specific user. Trying to figure out how to fix this. Link to Github Repo
Mongoose User Model
const mongoose = require('../db/connection')
const Schema = mongoose.Schema
const User = new Schema({
id: String,
name: String,
totalwins: Number,
description: String,
charactersID: [
{
type: Schema.Types.ObjectId,
ref: "Character"
}
]
})
module.exports = mongoose.model('User', User)
Mongoose Character Model
const mongoose = require('mongoose')
const Schema = mongoose.Schema
const Character = new Schema({
name: String,
wins: Number,
losses: Number,
percentage: Number,
image: String
})
module.exports = mongoose.model('Character', Character)
const graphql = require('graphql')
const { GraphQLSchema, GraphQLObjectType, GraphQLString, GraphQLInt, GraphQLID, GraphQLList,
GraphQLNonNull } = graphql
const Character = require("../models/Character")
const User = require("../models/User")
Types
// User Schema
const userType = new GraphQLObjectType({
name: 'User',
fields : () => ({
_id: {type: GraphQLID},
name : { type: GraphQLString},
totalwins : { type: GraphQLInt },
description : { type: GraphQLString },
character : {
type : new GraphQLList(characterType),
resolve(parent, args){
return Character.find({charactersID: parent.id})
}
}
})
})
// Character Schema
const characterType = new GraphQLObjectType({
name: 'Character',
fields : () => ({
id: {type: GraphQLID},
name : { type: GraphQLString},
wins : { type: GraphQLInt },
losses : { type: GraphQLInt },
percentage: {type: (GraphQLInt)},
image: { type: GraphQLString },
})
})
Query
//query the graph to grab the data
const Query = new GraphQLObjectType({
name: 'Query',
fields: {
user : {
type: userType,
// arguments passed by the user while making the query
args: {id : {type : GraphQLID}},
resolve(parent, args){
// return User.find((item) => { return item.id == args.id});
//finding a single user by id
return User.findById(args.id)
}
},
users : {
type: new GraphQLList(userType),
resolve(parent, args) {
return User.find({})
}
},
character : {
type: characterType,
args: {id : {type : GraphQLID}},
resolve(parent, args){
return Character.findById(args.id)
}
},
characters : {
type: new GraphQLList(characterType),
resolve(parent, args) {
return Character.find({})
}
}
}
})
Mutations
//allows user to add, update and delete to mondodb through graphql
const Mutation = new GraphQLObjectType({
name: 'Mutation',
fields: {
addUser: {
type: userType,
args: {
name: {type: GraphQLNonNull(GraphQLString)},
totalwins: {type: (GraphQLInt)},
description: {type: (GraphQLString)},
charactersID: { type: new GraphQLNonNull(GraphQLID)}
},
resolve(parent, args){
let user = new User({
name: args.name,
totalwins: args.totalwins,
description: args.description,
charactersID: args.charactersID
})
return user.save()
}
},
addCharacter: {
type: characterType,
args: {
name: {type: GraphQLNonNull(GraphQLString)},
wins: {type: (GraphQLInt)},
losses: {type: (GraphQLInt)},
percentage: {type: (GraphQLInt)},
image: {type: (GraphQLString)},
},
resolve(parent, args){
let character = new Character({
name: args.name,
wins: args.wins,
losses: args.losses,
percentage: args.percentage,
image: args.image
})
return character.save()
}
},
deleteUser: {
type: userType,
args: {
id: {type: new GraphQLNonNull(GraphQLString)}
},
resolve(parent, args){
const remUser = User.findByIdAndRemove(args.id)
if(!remUser){
throw new Error('No character found')
}
return remUser
}
},
deleteCharacter: {
type: characterType,
args: {
id: {type: new GraphQLNonNull(GraphQLString)}
},
resolve(parent, args){
const remCharacter = Character.findByIdAndRemove(args.id)
if(!remCharacter){
throw new Error('No character found')
}
return remCharacter
}
},
}
})
module.exports = new GraphQLSchema({ query : Query, mutation : Mutation})
Image of results from Grapiql interface