Building Next Generation Apps with Next.js and MongoDB - Ado Kukic (MongoDB)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello and welcome to nexjs conf i'm so excited that you're here and i hope you're excited as i am to spend the day learning all about the future of nextjs picking up some best practices along the way and connecting with the community at large my name is otto cookish and i work as a developer advocate at mongodb today i'm going to show you why i believe nexjs when paired with mongodb atlas delivers an amazing developer experience allowing you to build and scale your application regardless of what your project manager throws at you let's get to it the title of my talk today is building next generation applications with next.js and mongodb and if you know me you'll know that i'm not one for too many slides but before we jump into live code i thought i would spend a minute or two setting up the playing field now we know that developers love next.js but why is it the technology and features like incremental static regeneration or server-side rendering perhaps it's the zero configuration required for a production ready build file system routing is a pretty nifty feature but i bet what it really boils down to is the ability to easily create api endpoints allowing developers to easily expose data to multiple clients i'm just rambling off features of the framework and there are many many more i can list off but i don't think it's any of these features in isolation that make next js the logical choice for developers no i think it's something else i think it's related to the dunning-kruger effect and if you're not familiar it is a cognitive bias in which individuals with low ability or little exposure at a task greatly overestimate their skills or comprehension to translate this to developers when you pick up a new language or technology whether it's a language or framework like next.js and run through the quickstart guide you feel like an absolute rock star but as soon as you go to build something on your own you quickly run into issues and road roadblocks and setbacks and only when you really work at it and dedicate the right amount of time sift through the docks ask questions on stack overflow and so on will you start feeling like you know the technology so many technologies languages and frameworks are susceptible to the dunning-kruger effect due to their complexity next.js on the other hand is one of those rare frameworks that i believe is not it is a complex framework for sure but the team and community have put so much work behind it to ensure that the developer experience is superb from features and apis to the documentation to the community offering help guidance and examples nextgs is easy to pick up master and extend every time i've run into potential roadblocks with nexjs like loading third-party libraries that required the window element which breaks server-side rendering i was able to find a recommended solution that just made sense in minutes and in my case it was using nexjs's dynamic imports with ssr disabled in this talk we'll take a look at how we can extend nexjs to work with mongodb and the mongodb atlas platform all while maintaining that balance of productivity developer experience and ability to quickly and easily iterate that next.js developers are used to mongodb atlas is a database as a service offering that removes the complexities of management scaling and deployment and allows developers to quickly connect their applications to their data mongodb atlas is not just a cloud database though in addition to the mongodb nosql database atlas provides a lucine-powered search for your data a server-less platform with graphql support built right in and all of this is fully managed for you across a multi-cloud environment there are many more features and functionalities i can talk about and you can learn all about them at the mongodb discord booth so find me there and we'll keep the conversation going but for now let's jump into some code and see how easy it is to utilize some of these capabilities with next.js all right let's get to the code the best way to get started with next.js and mongodb is to utilize the with mongodb example and that's what we'll do here so let's create a new nextgs application by running npx create next app and we'll pass in the example parameter with mongodb and we'll name our application next bnb while the package is installed i do want to give a shout out and a public thank you to ash connell and matt carloda for contributing to the with mongodb example and fixing some of the connection pooling issues that i ran into now that our example is downloaded and packages installed let's open up our directory connect our next.js application to mongodb all we'll need to do is provide our mongodb connection strings to our environment we can find these connection strings within the mongodb atlas dashboard but this also works with any installation of mongodb so if you have a local installation a dockerized deployment or mongodb already deployed on your own cloud this will work just fine before we connect our app though let's talk a bit about the app that we're going to build and how we'll do it so due to covet 19 we have been tasked with modernizing a property booking website called next bnb we have a data set in mongodb atlas and we want to connect it to our next js powered frontend we want to allow the user to discover properties get additional details about them and even search for the right place and we'll start by exploring our data set and connecting mongodb to our application so let's go to our browser and look at the mongodb atlas dashboard all right so let's sign in to our mongodb atlas dashboard we'll hit sign in i'm going to log in with google and my account once we are authenticated and on the mongodb atlas dashboard to get our connection strings to connect to our data all we have to do is click the connect button connect your application and we will see our connection string presented here so what i'll do is copy the connection string and paste it into the mongodb uri field and i'll have to update the password because that's not provided by default and in my example here my password is mongodb and the database that we're going to connect to is called sample airbnb and again we'll provide that here as our database name airbnb let's take a look at the sample airbnb database and see what kind of data is held within it so i'll go back to the browser i'll close our connection modal and click the collections button from here we'll be able to see all of the databases that are within our deployment and here we have our sample airbnb database that has one collection called listings and reviews and here we have over 5000 different properties that we can look at and by default we get the first 20 displayed and we see all sorts of data so we can see the the name of the property a summary of it how many bedrooms what type of property it is and so on and so forth and if you're not familiar with nosql databases the really cool thing about them is that you can nest data so for example if we take a look at our amenities array it has a bunch of additional information that in a traditional sql database we would have to store in a different table so this is one example um additionally we can store reviews which are objects which are more more complex data types directly into this single collection so that retrieving this data is very very fast for us and we'll take a closer look into how we can work with this data as we build our application but for now let's go ahead and start our next gen application and make sure that we are connected and good to go i will also change this env.local to remove the example otherwise it's not going to work so now let's start our next.js application by running by running npm run dev and our application is going to compile and be served on localhost 3000 so let's just go ahead and make sure that this works we'll go back to our browser open up a new tab and navigate to localhost 3000 and now we see the traditional welcome to nextjs message but since we are using the with mongodb example we have the message next to us with mongodb and the other thing that we really care about is seeing the you are connected to mongodb message what this is going to tell us is that our connection string was accepted that we were able to successfully connect to our mongodb database now before we build the rest of our application let's take a look at the code that connects mongodb to next.js it lives here in this utility package and the file mongodb js and essentially the way that this works is we get our mongodb uri and mongodb database from the environment and then we simply create a function called connected database that is going to cache our connection so we don't want to create a new connection every single time a request is made whether from an api route a statically generated route or a server-side rendered route so once we are connected we are going to cache our mongodb connection so that we can reuse it and then we're going to connect to the specific database that we want to connect to and then we're going to return all of that as a promise and for our example just on the index page we have a server side rendered function so we're using get server-side props we are connecting to that database so we are getting that connection and then all we're checking for is to see if our client is connected and if it is we're going to return true and if it's not we're going to return false and then we're sending that as a prop to our component now in the interest of time i'm going to fast forward a little bit and create a few pages that are going to represent our ui for the application and then we'll get back to working with nexjs and mongodb so bear with me for just a second alright so we've replaced the default welcome page with our home page ui for the next bmv app and if we take a look at what it looks like all we're doing is mapping over a properties array so we're going to get a list of properties from mongodb and we're going to display that information in nicely formatted tailwind css cards and we're going to display the property image property name the number of guests that it can hold where it's located as well as the pricing information so we have this ui built out but if we go into our application and refresh we're not going to see them because we haven't made the call to mongodb yet to get that data so let's do that so we'll start by removing the existing boilerplate code we have here so we're not gonna need the is connected anymore and instead of the client what we're going to connect to is our database so this is going to allow us to work with that sample airbnb database and the first thing we're going to do is make a call using the get server-side props function so when our page is loaded we're going to execute this code and we're going to call database dot collection and this is going to ask us which collection do we want to search for and the collection is listings and reviews and what we're going to execute on this collection is a find operation so we'll say find and this is all using the native mongodb driver so all of the methods here were created by the mongodb db team to allow you to interface with mongodb within a node.js environment and since next.js is that this works just fine next what we're going to do is we're going to sort the data we get back so we're not going to pass in any parameters to define we just want to get all the data and we will sort it in ascending order based on its id so to sort in mongodb you simply pass the sort method decide which key you want to sort on and we're going to do underscore id and we'll say in ascending order and then we are going to limit our result count so we only want to get back say the first 30 or 40 results let's just limit it to the first 40 documents to get returned and then we're going to call this to array method to convert the cursor to a javascript object now if we were to just do this and you know let's store this data in a variable so that we can save it and since this returns a promise we can use async await if we were to just do this and just try to pass the data directly to our props we would get an error and the error would say hey i can't serialize this data you know you're using all sorts of bson data types that javascript doesn't understand so what we're going to need to do is we're going to map over this data set and just get the properties that we care about so let's do that next i will create a new variable called properties and all we're going to do is map over the data we get back from mongodb so we'll say data map and property so every document we get back will be one property so i think property is a fitting name here and then from here we're just going to return the data types that we care about so if we go up here and take a look we have image name guests address summary and pricing information so let's return a new object and we'll set the name property to property.name we'll set the image to property images dot picture url and all of these data types if you're curious where they're coming from they're coming from our mongodb database so if we were to try to find where the images are they live under images and then picture url so we have our image we have our address which is property dot address we have our guests property dot number of accommodations our account dates and then we have our price and we have our cleaning fee now in our data set these are set as uh decimal 128 data types so we can't simply just say property property.price for example if we did when we go to render our page we're going to get an error so to fix this what we're going to do is we are first going to stringify our price and then we're going to parse it and that's going to give us the value so so one way to do this is within this map function we'll say um cons price and we'll parse and stringify our property.price now what this is going to return is it's going to return a object and so so we still can't do simply price because that that's going to return an object uh what we need to do is say price dot number decimal so so that's going to give us the actual value the actual value the actual price and then for the cleaning fee we're going to do something a little different as well because not all the properties have a cleaning fee and with mongodb you are not required to have each document match a specific schema you absolutely can enforce a schema on the mongodb side but if you wanted to be flexible and if you had a kind of fluid data model that was constantly changing you may have certain documents that don't have certain fields so what we're going to do for the cleaning fee is by default we'll say that the cleaning fee is zero and then if our property does have the cleaning fee property so it's not undefined then we're going to set the cleaning fee again to that json.parse json dot stringify and property dot cleaning fee and then remember since we are doing this and this is going to return an object what we can also do is set this cleaning fee to cleaning feed dot number decimal and then here we can just use the leading fee property and then finally once we get all of our information so we're getting the data from the database we are formatting it to our needs we are going to pass it as a prop and return that data to our component and then if we take a look at our component up here we are getting that that property's data and then now if we go back into our application we should see our list of properties so let's do that i will go back into my browser create next app and refresh the page and if everything worked we should see a list of properties but we do not so it looks like we have an error in our code let's take a look again we are live coding so it looks like we had the wrong collection name so it should be listings and reviews we'll save that go back into our code so if we go back into our application refresh now we see our list of properties from mongodb and it looks like we also did forget an additional attribute which was the summary so let's do this really quickly and now we have a lot more information about each of the properties and then we can click on the details button which is going to take us to view the details of the specific property but we haven't built out that page yet so let's go ahead and do that as well so in our index home page we used the get server side props method which is going to run every single time we reload the page we're going to connect to mongodb get the latest list of properties and display them for the listing information i think it would be a good idea to use the get static props method instead to pre-render and cache this data because i don't think the property listings are going to change all that off so let's do that in the id page so i already created a listing id page and it looks pretty similar to the index home page we're still displaying a bunch of property information uh the big change here is we're only going to display one property at a time and we're also adding the amenities that that property offers and again we're going to get this from mongodb now if you're not familiar with getstatic props and static site generation the way that this works is we run this method at build time to get the data from mongodb and generate the pages ahead of time but thanks to next.js is incremental static regeneration we are allowed to update pages on the fly as well giving us the best of both worlds so let's see how this works the first thing we'll need to do in a statically generated page is have a method called get static paths which is going to tell us which paths to pre-render ahead of time so let's create that function get static paths and in this example we're not going to render any pages ahead of time so we're just going to return an empty paths array but we are going to set this fallback property to true and what this is going to do is it's going to tell next js that if we land on a path um go ahead and actually run the get static props method and get the data at at runtime all right so let's go ahead and implement this function and the way it's going to look is we're going to create the getstaticprops function and we're going to capture the parameters which are going to map to this id here so we're going to be able to do params.id to get the id of a specific property then let's connect to our database like we normally would so i'll connect the database and then to get our data we'll say await dv dot collection and again the collection is going to be the same listings and reviews but now instead of running a find operation and i'll do this on a new line we'll say find one and in this fine one if we don't pass any additional parameters into this method we are going to get the first document in the collection but we want to get a specific property so the first thing that we're going to pass the first argument is going to be an object that is going to tell us how to filter and what to find so we're going to look at the id field in our mongodb collection and we're going to match it to the parameters id that our browser provides and then we're also going to pass in an options object which is going to allow us to do a couple of other nice things and the big thing here that we want to do is add a projection and what a projection is is telling mongodb to only return the fields that we ask for so rather than getting all the data like we did in the homepage example a projection is going to allow us to get back a subset of the fields within a document so the documents that we'll want to get back are these so we're going to get back the name images address summary price cleaning fee and the list of amen amenities for a property and once we have this what we'll do since here we're just getting one item instead of an array we'll just return our props which is going to be the property and then we can do the json parse json stringify here and it's going to be on the data so we're not creating an additional um value for it but we'll need to do one more thing here and that is add this revalidate field and what this real validate is going to do is it's going to tell next.js how often it should check with mongodb for new data and in my case here i'll just set it to 1 so that whenever we load this page the next time it's refreshed we're going to run this function again and get the latest and greatest property data so in this way we would get the best of both worlds so we would be able to statically generate any of the paths that we provide but since we have the fallback set to true and we have this revalidate set to set to one or check every second what it's going to do is it's going to allow us to get data as it's added to the database as it's updated and we're going to be able to get the latest and greatest data so let's go see if this works i've saved here let's refresh and let's refresh our browser and click on one of the properties and now we get the listing and again it's the same information with the addition of all of the amenities that the property provides and if we go back we should be able to select any other one so let's say details here we'll be able to get the information but again the reason that we're able to do this is because we have set the revalidate to 1 and the fallback to true if we were to change this and say false now at build time when our application is built only the paths that are provided in here would get statically generated and additional pages we would get a 404 on so if we go back to the home page and try to click on the details for this property for example we'll get a 404. now before we close out the talk i do also want to show you mongodb atlas search and how you can use the lucine powered search to very easily add search capabilities within your next.js application so let's do that next to add mongodb atlas search capabilities to your database we'll need to create a search index and the way that this works is we'll go into our mongodb atlas dashboard we'll find a database that we want to add search on and we'll click the search indexes tab from here we'll simply create a search index and here we have all sorts of properties that we can configure but for our use case here we'll just set the dynamic mappings to true which is going to allow mongodb atlas to figure out how to create the search index by itself so we'll hit create index and this is going to take a few minutes to build the index so while it does that why don't we go ahead and implement our api route all right let's go and create that api route so within the pages directory we can create a special directory called api and any file that we create in this api directory immediately becomes an api a rest based api endpoint so we'll create one called search.js and in here all we're going to do is create a handler function to handle the request that comes in and when we deploy this application if we deploy it to versel it's automatically going to create serverless functions for us otherwise if we deploy to our own infrastructure it's going to set up a node.js express application to handle it for us so let's go ahead and create this api endpoint we'll say export default async function and it's just going to be our handler that takes in a request and sends back a response and the first thing we're going to want to do is connect to our database our mongodb database the same way we connected in the get server side props and the get static props so we'll get our database by calling connect to database and we'll have to import this from our mongodb utility package so we can use this same call in both the api routes as well as the next js routes and then from here we'll capture the search term that the user searches for so let's say const term and we can get this from the request query and we'll call it term and now to implement our search functionality what we're going to do is we're going to make a call to mongodb so we'll see db.collection and we're still working off of that same listings and reviews collection and instead of using a find or find one operation we're going to make use of the mongodb aggregation pipeline so we're going to use the aggregate method to create our pipeline and if you're not familiar with the mongodb aggregation pipeline it is a way to aggregate your mongodb data as well as run native mongodb server operations and in this case we're going to be using one of those which is going to be called search so our first stage in this pipeline is going to be called search and this takes in an object which is a search and for this search capability we at the bare minimum have to pass in two different fields a query and a path the query is going to be the term that we want to search for and here we're using term which is going to be the term that the user provides and the path is going to be the fields within our document that we want to perform the search on so in our case we're going to say description and amenities so when our user searches for things like awesome we're going to look into all of our documents and look at their description and their amenities and if they have the keyword awesome we're going to use that result now that is the first stage of our pipeline we can add as many stages as we want but we'll add just one more to show you how this works and our second stage is just going to be a limit stage which is going to tell us how many documents to return and let's just say 20 documents is good enough finally since we are getting back an array of data we'll call the to array method to transform the cursor to a json object and then we'll finally send that data to the browser by using response json and sending our data let's test our search functionality let's go into our browser and let's call that api endpoint so we'll say api search and for the search term let's pass in awesome this is going to give us back a result set where in the description or in the amenities we have the keyword awesome pretty cool right but it doesn't stop there with mongodb atlas search you have additional features and functionality like typo tolerance to implement fuzzy search autocomplete custom scoring and much much more all natively built into your mongodb deployment there is so much more i can talk about when it comes to pairing next js with mongodb but i think that's enough for today next js and mongodb go hand in hand to provide an amazing developer experience and i hope that i was able to give you a small glimpse of the capabilities today i can't wait to see what you will build if you have any questions come chat with us at the mongodb virtual booth join us at community.mongodb.com and enjoy the rest of the conference you
Info
Channel: Vercel
Views: 8,982
Rating: 4.9344263 out of 5
Keywords:
Id: MOqkfQIMdLE
Channel Id: undefined
Length: 32min 28sec (1948 seconds)
Published: Tue Nov 17 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.