#5 GraphQL + MongoDB | Build a Complete App with GraphQL, Node.js, MongoDB and React.js
ฝัง
- เผยแพร่เมื่อ 9 ก.พ. 2025
- Time to leave the in-memory storage world and add a real database to the GraphQL API. Time for MongoDB to be connected to this Node + GraphQL app.
----------
Node.js full course (includes GraphQL): acad.link/nodejs
React.js full course: acad.link/reactjs
MongoDB full course: acad.link/mongodb
Learn more about the type system: graphql.org/le...
Finished Code: github.com/aca...
Complete Playlist: academind.com/...
Want to learn something totally different? Check out all other courses: academind.com/...
----------
• You can follow Max on Twitter (@maxedapps).
• And you should of course also follow @academind_real.
• You can also find us on Facebook.( / academindchannel )
• Or visit our Website (www.academind.com) and subscribe to our newsletter!
See you in the videos!
----------
Academind is your source for online education in the areas of web development, frontend web development, backend web development, programming, coding and data science! No matter if you are looking for a tutorial, a course, a crash course, an introduction, an online tutorial or any related video, we try our best to offer you the content you are looking for. Our topics include Angular, React, Vue, Html, CSS, JavaScript, TypeScript, Redux, Nuxt.js, RxJs, Bootstrap, Laravel, Node.js, Progressive Web Apps (PWA), Ionic, React Native, Regular Expressions (RegEx), Stencil, Power BI, Amazon Web Services (AWS), Firebase or other topics, make sure to have a look at this channel or at academind.com to find the learning resource of your choice!
I was looking for easy understanding GraphQL + MongoDB tutorial, then I found this. Thank you in deed.
Can't wait for the next parts! Great series Max!
Happy to read that Jasper, the series will continue next week!
You are now my favorite tutor , Max! Great job man !
So happy to read that Martin, thank you for your support!
Frontend guy here. Having so much fun, thanks a ton 😊
29:40 I am able to query _id without having to call .toString on it. Looks like they updated GraphQL, no?
that moment when you expect to get an error but it works
@@matheusvalandro2093 I'm pretty new to writing code, but yeah, looking forward to these moments :)
this same.
Yes I got back the _id as well.
Yeah me too, it works. Seems they fixed it.
For anyone looking on this and having troubles connecting to Atlas. Although node -v gave me version 11.x atlas link to node 3 and above did not work. After looking into option errors etc i tried to link to version 2.2 and above. This actually worked for some reason. Still trying to figure this out, but hey its working ! :D
Thank you so much for figuring this out!
Great tutorial! Learnt to use mongo DB and mongoose for the first time along with GraphQL. Thanks Max!
That's really cool to read, thanks a lot for sharing this Josiah!
you're a legend for doing these for free. Thanks so much brother.
Thank YOU for your awesome feedback Paul!
i like this video, because who talk obviosly know what he do, even if he made a mistake he know exactly where it was made and what, unlike alot other guy who have create tutorials :D
Happy to read that you like the video and my explanation style, thank you :)
I think mongoose actually also recognizes "id" whenever you are declaring your types in the graphQL schema. Therefore there is no need to add "_id".
maybe it was added later, I noticed this detail too now, but still decided to leave "event . id" feature, just in case))
In mongoose schema, you can use
date: {
type: Date,
default: Date.now // don't put now()
}
Also if you want auto add created date and updated date just add to end of the schema this option { timestamps: true }
When you're not going to re-save a document you've queried for you should use .lean() so that mongoose doesn't hydrate the document
You also do not need to use _doc (even on the mutation)
events: async () => {
try {
return await Event.find().lean();
} catch (err) {
throw err;
}
}
is perfectly acceptable
You don't need lean, it just saves you some processing in the case that you don't need mongoose's document functionality.
Awesome series and tutorial, thanks Max !
Happy to read that you like it John, thank you!
Brilliant Max, exaclty what I needed! I'n new to your channel - Subscribed.
Welcome aboard!
I think that since this video was made mongoose resolves the _id discrepancy and it is no longer necessary to do: ```_id:event._doc._id.toString() ```
seems like that, I've tried both and it worked either way!
Why I got all null as result in graphql?
Could anyone explain me?
getMessages: async () => {
const msgs = await MessagesModel.find();
return msgs.map((msg) => {
console.log(msg);
return {
...msg._doc,
id: msg.id,
};
});
},
Awesome Series Max, Subscribed.
Thank you for your awesome feedback and support Prabhjeet, happy to have you on board :)
Awsome explanation Dear teacher
Great job mate, i recommended your channels to all my peers. And this tutorial is a part of my #100daysofcode challenge 😜
Thank you Abhin and all the best for your challenge :)
Thank u for this awesome video and series, Max and I am waiting for next video on this series
Thank YOU for your support Abhishek, the next videos will be released this week!
At 21:33, line 67 should be: return { ...result._doc, _id: result._doc._id.toString() };
When you fetch the events from mongo at 27:30. Couldn't you use .lean() instead of mapping and destructing the result?
Man, you teach very well.
Really great video series here. Provides a detailed and to the point implementation of GraphQL basics and setup.
I did receive a TransientTransactionError when I used a template literal and added useNewUrlParser.
When I removed it, I received that the password contained an illegal unescaped character so this prompted me to remove the template literal and write in the username and password within a string which finally allowed me to connect to the db. Pretty odd but glad I figured it out.
i really like your tutorials, really great job, congratulations
Great video!
We can also use .lean() method provided by mongoose to get raw reponse from DB query.
So you don't need to convert your response into object. Also .lean() helps to convert object type _id in string ;)
return Event.find().lean().then(events => {
return events;
}).catch(error => {
throw error
});
Great tutorial! I don't know if it wasn't supported back when you made the video, or maybe it was uncommon, but why didn't you use async/await? Less headache than .then.catch chains. It also brings back the try+catch into the JS game.
Great As Always, Thanks Max!!
Really nice series man!
Hey max how to use graphl query items in mongo find method. And also how can we use graphql with Agreegate queries.
I was curious why you used the "._doc" method to strip out the mongodb metadata from the ".find()" method. I thought that graphql will only return the fields requested by the client (frontend) query. So no mongodb metadata would be returned to the client. This means no wasted bandwidth returning unwanted metadata or extra parsing/filtering by the client. Was it done to somehow optimize the backend performance when processing the graphql query?
Great video! Love learning graphql. I am having a problem though - every time I use return an object with the spread operator (as in return {...result._doc}) my app crashes. I tried it with simply:
return result;
and
return event;
instead of the spread operator or anything else. This seemed to work for me all the way around, and gave me the right return when I tried createEvent and then query:
{
"data": {
"events": [
{
"title": "A test",
"_id": "5c41fd23c4f1073c3caf1868"
}
]
}
}
But am I receiving unnecessary meta data somewhere hidden? Also, why is my app crashing whenever I use return {...result._doc}; or return {...event._doc}?
Thanks!
Please help, at 23:39 my object returns createEvent: null
So it looks like this: {
"data": {
"createEvent": null
}
}
and the query looks like mutation {createEvent(eventInput:{title:"YO test", description:"testing again ugh", price: 100.00, date:"2019-05-03T14:54:42.643Z"}) {
title
}
}
Make sure in app.js that inside of the createEvent function, that you have "const event = new Event({..." making sure the 'e' is lowercase in the variable declaration name. I got this exact error and finally figured out what was causing it.
Were u able to solve it??
Cause i am getting the same error
And dont know what's causing it
vey nice! keep doing this great project
Thank you David, the next videos will be released next week :)
This is just awesome, danke für alles.
Danke DIR für deinen Kommentar :)
ty a lot for this serie of videos
I have an error :( Server selection timed out after 30000 ms
at new MongooseTimeoutError
What would the date return if he did a query for events { date }? Since its stored in MongoDb as a Date type, but the query type says date is a String? He never shows this...
Great video! My graphql api worked without removing the mongodb meta data. If i dont remove it would it cause longer parsing or network time?
Hey Max, quick question! I've been following along the series but making tweaks to fit a personal project. With GraphQL, I understand we can type them as Strings and Ints and such, but what if I want an array of Strings as one of the parameters (parameters as in the title description date id etc).
I want to add tags, or keywords, so that a user would be able to tag it as "music" "post malone" etc but mapped to one object. Any idea how to accomplish this?
I could be wrong here, but I believe you could just replace "events" in the RootQuery with "music" or "songs" than define the schema for it both as a type and in mongoose. But it appears in general you can make a new type and put it in as a sort of "object" as we did here with Event (capital "E").
Let me know if I'm wrong.
Very well explained.
Help, please. When I try to connect database, i get this error- Error: Password contains an illegal unescaped character , but i've got only letters in my password. What should I do?
try to type url in one string
@@Gorr1995 this fixed the error for me. do u know why this is?
@@marcellosanagustin670 I had the same problem that fixed it, Thank you!
why do we need to pass title with the createEvent at the end?
For me `events: () => Event.find()` works just fine out of the box. It stringifies the id automatically as well.
same, maybe mongoDB changed something
Max you rock!
Is it ok to use TypeScript for building this application?
My mongoose.connect not working, when I show an error my ${process.env.MONGO_USER} and ${process.env.MONGO_PASSWORD} are undefined
Im sadly getting this error and have no idea how to solve it:
{ Error: querySrv ENODATA _mongodb._tcp.cluster0-uhhgj.mongodb.net
at QueryReqWrap.onresolve [as oncomplete] (dns.js:196:19)
errno: 'ENODATA',
code: 'ENODATA',
syscall: 'querySrv',
hostname: '_mongodb._tcp.cluster0-uhhgj.mongodb.net' }
[nodemon] clean exit - waiting for changes before restart
solved it sofar by using the Node.js driver version 2.2.12 and then doing:
mongoose.connect(mongooseURL,
{ useNewUrlParser: true, useUnifiedTopology: true })
.then(() => {
stack.listen(3000)
})
.catch(error => {
console.log('error:', error)
})
And follow up question, when we are doing
mutation {
Event(eventInput:{title:"", desc:"", date:""}) {
title
}
}
what does title do in between the parameters? Is it telling GraphQL that title is the only information we can grab from the event we just added?
Basically yes, it's like a response form a post. You are saying: Please persist my data, and then if everything is ok, return newly persisted "title" back
Awesome tutorial series Max. Once again!
Is it really necessary to pick out the "core" of the retrieved document by using _doc and stuff? Isn't it filtered anyway before it gets sent to the client? What's the advantage of this technique?
Greetings from Mannheim :)
welcome back to this serious? I'm dead serious! love ur tuts btw
Hi @Max - I really impressed by your detailed explanation. Thank you for the great tutorial. One thing I want to understand here is, how the collection 'events' created? We are not mentioning anywhere that collection name should be 'events' right? Thanks in advance.
Where do we define the name of the collection which is "events" in this case ?
It gets defined automaticly by the name of your model. For example tree = trees, car = cars
Keep doing this gud work
I'll try my best to do so Jaga :)
Hey, what's the code formatting extension you use in VSCode?
It's a default setting, just look for "format document" in the keyboard shortcuts.
Great video! But I feel completely uncomfortable with {...result._doc}. Casting to plain JS object by using ".toObject()" seems to be more correct.
Great tutorials thanks for making them they are great! What's the extensions for the cool icons?
Thank you Pedro! That's the Material Icon theme.
@@academind another question, do you think this approach will change a lot if couchdb is used instead of mongodb? many thanks
Awesome! Thanks
Are we gonna cover on how to write and query within nested objects? for example: *"price": {"cost": 9.99, "retail": 15.99}*
Max, you are IRON MAN of web world :)
I just have one doubt though:
@line 49 using "return [...events];" we will get the same output (no error with _id value too) . Is there any disadvantage of using it?
I am getting Error
(node:13644) DeprecationWarning: current URL string parser is deprecated, and will be removed in a f
uture version. To use the new parser, pass option { useNewUrlParser: true } to MongoClient.connect.
{ MongoNetworkError: connection 4 to cluster0-shard-00-00-tn8ty.mongodb.net:27017 closed
at TLSSocket. (C:\xampp\htdocs\Event
ode_modules\mongodb-core\lib\connection\connect
ion.js:276:9)
at Object.onceWrapper (events.js:277:13)
at TLSSocket.emit (events.js:194:15)
at _handle.close (net.js:600:12)
at TCP.done (_tls_wrap.js:388:7)
name: 'MongoNetworkError',
errorLabels: [ 'TransientTransactionError' ],
[Symbol(mongoErrorContextSymbol)]: {} }
[nodemon] clean exit - waiting for changes before restart
I had the same error. Fixed it by adding this property { useNewUrlParser: true } in the mongoose.connect() function. So your function should look something like that :
mongoose.connect(
`mongodb+srv://${process.env.MONGO_USER}:${process.env.MONGO_PASSWORD}@the_rest_of_the_address_you_copied_from_mongodb`, { useNewUrlParser: true }
).then(() => {
app.listen(3000);
})
.catch(err => {
console.log(err);
});
hey,great work ,please bring a new series on graphql with relay ....
can you do a tutorial on how to use prisma with GraphQL and apollo ?
Hey guys do we ever build a separate file for graphql for the schema?
yes
Does anyone know the steps, libraries and packages required to connect to MySQL database?
I have an issue here. My Graphiql does not return the title. It just spins and and nothing hits the db
Ended up not whitelisting the proper IP
You can fix the deprecation like this: mongoose
.connect(
`mongodb+srv://${process.env.MONGO_USER}:${
process.env.MONGO_PASSWORD
}@`,
{ useNewUrlParser: true }
)
I'm following your video and I'm getting an error:
name: 'MongoNetworkError',
errorLabels: [ 'TransientTransactionError' ],
[Symbol(mongoErrorContextSymbol)]: {} }
[nodemon] clean exit - waiting for changes before restart
Is that a mongodb configuration issue or what, any ideas?
I've fix that problem. I just use wrong cluster.
@@rhema93 were you having this error: " MongoNetworkError: failed to connect to server [server] on first connect"?
@@davida5607 I had this error in terminal, and it was because I used wrong credentials in order to connect with db.
Does anyone know how to save checkbox info and save that data to the db?
Am I the only one not being able to open Graphql at 22:40?
Nope, just ran into the same issue. Check if you have graphiql: true and restart the server again.
Max, can we use async / await to handle the promise when accessing mongodb?
Just wait and see 😉
@@mrskylerriley This guy re-watching videos =)
can I use dotenv rather than nodemon.json?
yes!
For anyone getting the following error:
MongoNetworkError: failed to connect to server [fooClusterStuff] on first connect [MongoError: bad auth Authentication failed.]
you need to remove the from your uri string.
foocluster.d0xng.mongodb.net/?retryWrites=true&w=majority should be foocluster.d0xng.mongodb.net/test?retryWrites=true&w=majority
! Make sure that your 'MONGO_PASSWORD' does not contain any non-alphanumeric characters !
Not sure why, but when I insert my username/password/clustername into my url as he does in the video it doesn't work for me. What I did to make it work is put the entire url in a const with the process.env names inserted and that made it work. Any ideas why?
@@stephenjhartfield If you create a proper Template Literal string with the mongo values assigned to a const 'connectionStr' and then use that in the db connection method successfully, I don't see why you shouldn't be able to copy that exact string and replace it with the variable 'connectionString'.
@@mrskylerriley Yep you are right. Does work now, must have been my mistake somewhere, thanks!
This video code using typegraphql and typeorm with postgres - github.com/reactivicky/eventbooking-typegraphql/tree/5graphql%2Bmongodb
Thanks for the great tutorials on Udemy as well as youtube. Have you considered doing a fullstack with apollo server 2 apolloclient and apollo boost?
Thanks for your awesome feedback! At the moment I got no plans regarding such a tutorial, sorry.
you not need --save when you run npm i
when using npm version 5 and above
I'm getting an error:
Error: Username contains an illegal unescaped character, can somebody help me?
Here is the string for the DB-connection:
`mongodb+srv://${process.env.MONGO_USER}:${process.env.MONGO_PASSWORD}@cluster0-cpkkj.mongodb.net/${process.env.MONGO_DB}?retryWrites=true&w=majority`
Please note that you have to provide it without a RETURN/LINEFEED in between
@@bCool-sl5cy yes, this helped a lot, thank you so much!
@@arpandutta3591 you are welcome.
I get 'MongoNetworkError',
errorLabels: [ 'TransientTransactionError' ], [Symbol(mongoErrorContextSymbol)]: {}
change IPwhitelist
Cool stuff, however, what is the point in using packages that will be depricated?
Hi I am requesting you to please give me some solution to get rid out of this error'
that error is very hard to solve, because only god can see it.
Instead of creating nodemon.json it is better to install/use dotenv. It is not a good idea to store any kind of credentials in a repository.
you could just add it to your git ignore but you're right about storing credentials
Those who are having issues with connecting to the atlas serve. Instead of using my current IP address from the atlas, search for your IP address in google search. (Solution from StackOverflow
you dont need to write all that for _id anymore in the new graphql version
Hey Max,
Can you provide an example to not be able to save duplicates in mongodb based on the title or description of an event
title: {type: String, unique: true} - it will be done by Mongoose
@@naughtrussel5787 tried that and still getting duplicate titles
@@donvitocorleone187 , there are some cases, when this makes no effect, e.g when collection already exists and you added this parameter, or you already have duplicates, and some other cases. This can be solved by enabling index on this field manually. You can do this via addind parameters to whole schema, or explicitly sending such command via mongoose stuff, but i prefer connecting to mongoshell and manually creating index on specific field. Indexes in mongo guarantee that value is unique, otherwise you will get E1100 Duplicate Index Error.
what is +args?
it casts to number
Hi ,
I am facing the below error while executing node app.js:
(node:7556) DeprecationWarning: current URL string parser is deprecated, and will be removed in a future version. To use the new parser, pass option { useNewUrlParser: true } to MongoClient.connect.
Error is { MongoError: authentication fail
at E:\prototype_server
ode_modules\mongodb-core\lib\topologies
eplset.js:1458:15
at E:\prototype_server
ode_modules\mongodb-core\lib\connection\pool.js:869:7
at E:\prototype_server
ode_modules\mongodb-core\lib\connection\pool.js:845:20
at E:\prototype_server
ode_modules\mongodb-core\lib\auth\scram.js:266:20
at E:\prototype_server
ode_modules\mongodb-core\lib\connection\pool.js:532:18
at process._tickCallback (internal/process/next_tick.js:61:11)
errors:
[ { name: 'cluster0-shard-00-00-xv671.mongodb.net:27017',
err: [MongoError] },
{ name: 'cluster0-shard-00-01-xv671.mongodb.net:27017',
err: [MongoError] },
{ name: 'cluster0-shard-00-02-xv671.mongodb.net:27017',
err: [MongoError] } ],
name: 'MongoError',
[Symbol(mongoErrorContextSymbol)]: {} }
i have this message when a want to start NPM :
(node:65484) DeprecationWarning: current URL string parser is deprecated, and will be removed in a future version. To use the new parser, pass option { useNewUrlParser: true } to MongoClient.connect.
{ MongoNetworkError: connection 5 to cluster0-shard-00-02-ntrwp.mongodb.net:27017 closed
at TLSSocket. (C:\xampp\htdocs\graphql-react
ode_modules\mongodb-core\lib\connection\connection.js:276:9)
at Object.onceWrapper (events.js:273:13)
at TLSSocket.emit (events.js:187:15)
at _handle.close (net.js:610:12)
at TCP.done (_tls_wrap.js:386:7)
name: 'MongoNetworkError',
errorLabels: [ 'TransientTransactionError' ],
[Symbol(mongoErrorContextSymbol)]: {} }
[nodemon] clean exit - waiting for changes before restart
stackoverflow.com/questions/50448272/avoid-current-url-string-parser-is-deprecated-warning-by-setting-usenewurlpars
I had the same error. Fixed it by adding this property { useNewUrlParser: true } in the mongoose.connect() function. So your function should look something like that :
mongoose.connect(
`mongodb+srv://${process.env.MONGO_USER}:${process.env.MONGO_PASSWORD}@the_rest_of_the_address_you_copied_from_mongodb`, { useNewUrlParser: true }
).then(() => {
app.listen(3000);
})
.catch(err => {
console.log(err);
});
Plz make similar video series with angular 6 .
He already has an awesome course on angular in udemy, in fact its the best selling course on udemy, check it out here www.udemy.com/the-complete-guide-to-angular-2/. get it, you will be glad