 Hey everyone, thanks for coming to MongoDB and single page web applications. My name is Josh Powell. Despite the t-shirt, I don't work for Tengen. I just went to one of their conferences, and a big fan. I am co-author of the book Single Page Web Applications, JavaScript end to end, that's being published by Manning. I've got 13 years of web application development experience. You can find out more on my blog jsjoshing.com. You can also find my book on jsjoshing.com as well. Or tomorrow there will be a Manning exhibit. You can go and go there. So this talk is going to be about single page web applications, what they are, how does Mongo fit into a single page application, showing how to use Mongo a little bit to ease development. And then that's about the first half of the talk. And then the second half will demonstrate end to end Mongo integration into a very rudimentary single page application. Then I'll show you how to use Node.js to monitor Mongo for updates to the collection, and then push them out to the web sockets and socket IO. So what is a single page application? At its simplest, it's a page that does not reload. So think about Gmail. When you update some information on the page, you only update the section of the page that changes, but the rest of the framework stays the same. That means that there's less code sent across the wire, that you get faster load times, and you end up with more responsive applications. There are several ways to do SPAs. Today, the usual ways are to do Flash or JavaScript. But in the past, there's also Java applets, or I guess you'd also use Silverlight or some other technologies. But today, JavaScript is really winning that battle for a few reasons. First is that browsers are very widely supported, and JavaScript is native to all browsers. So the users don't have to install any plugins and keep plugins up to date in order to use the application. Another reason is instead of having to know another language like Flash Action Script, you can work on a client in just one language, JavaScript. And deployment is trivial. You only need to host files on an HTTP server, and they will be accessible to anyone with web access. JavaScript over time has become truly cross-platform. As converging standards in JavaScript libraries like jQuery have made developing cross-browser JavaScript code fairly trivial. So even now, JavaScript can, at times, rival compiled languages in terms of speed. And JavaScript's only going to get faster as Microsoft, Google, and Apple battle it out for browser supremacy. And so modern JavaScript implementations can enjoy some advanced optimizations like just-in-time compilation to machine code, branch prediction, type inference, and multi-threading. And JavaScript now has access to some advanced features like web sockets, which allow server-initiated communications with all connected clients. The benefits of a single-page application are that it renders and responds like a desktop application. There is no click and wait, and having the screen flash through all the page re-renders. It is click, and just the relevant section of the page gets updated. An SBA can also notify users of the state of the application. Instead of relying on the browser to render its spinning icon somewhere in the browser Chrome, you can just update the section of your page it's going to change with your spinner icon, and users can continue to interact with the application while that slow section continues to load. Unlike a desktop application, an SBA is available anywhere that there's a browser. Whereas with a traditional desktop application, you're going to have to develop once for every OS you want it to run on. When deploying an SBA, it's instantly accessible to all of your users. There's no need for them to download and install an update. It's just available the next time they go to access the application. Whereas even with mobile phones today, in iOS, you're still dependent on the user going to the Apple Store and downloading the latest version. And so we've got weeks of time and people are on the latest code. So some drawbacks of an SBA, the business logic is all in the client. So as a benefit, and as a drawback, the drawback being that you've exposed your business logic to anybody that wants to go and look at it. So if you've got some proprietary algorithms, you probably want to keep them over on the server side. It tends to be more of a rare skill set. Java script UI experts are pretty difficult to find. And spot development is a rare, although a growing skill set, especially with new frameworks like backbone, spine, knockout, and others. Another drawback is that even though we've made a lot of progress with cross-browser issues, it still needs to be considered, especially around older browsers like IE6 and with CSS. With the JavaScript, we've got cross-browser libraries that help out. But with CSS, you still have to worry about the differences between different browsers. And finally, there's really no agreed upon client-side design pattern like there is for your traditional web application. They have NBC for those. But different frameworks are trying different things right now. You'll find MVVM, MVR, or the one we use in our book, MFC, which is model feature controller. So how does Mongo fit into an SPA, a single-page application? Well, there are three benefits. And these benefits are more about the form of the application. And I'm not going to go into so much. I'm not going to go into it all like benchmarking or scaling, but just talk about development of the application itself. So one benefit is when combined with Node.js, you can program in JavaScript from end to end in your application. The data structures that you're consuming on the client are being consumed in the exact same structure they're stored in in the database. And the ever-popular schema list, no migrations. So JavaScript end to end, of course, you've got your JavaScript on the client and the browser. On the server, you've got Node.js, which is just running the Chrome JavaScript engine on the server side to execute JavaScript. And then you've got MongoDB, which has a JavaScript interface for interacting with your data. So that's beneficial because it means less content switching, context switching for the developer, and less overall knowledge needed to get building a full stack applications. Somebody can learn JavaScript and immediately start writing full stack. Whereas if you're working in a traditional framework, you have to learn JavaScript, HTML, CSS, Ruby, Rails, SQL, or Java, Spring MVC, or PHP and Django, or whatever. But you have to know a whole lot of different things. So another advantage is that the data that's stored in the database is the exact same format and structure as needed on the client. This is your more traditional web application up here, where you'll make an Ajax call to the server that will be transmitted in JSON, which will then, on a Ruby on a Rails server, will be converted to Active Record. Active Record will then convert to SQL and issue the SQL queries against the relational database, which will then return its relational responses and convert those back to Active Record, which will then just be converted over to JSON and sent back across the wire to be consumed on the client side. Whereas if you're using Mongo and Node.js, you talk from the client JSON to the server JSON. You go from JSON to the server to the JSON to the database. JSON from the database back to the server, and then JSON on to the client to be consumed. So you're spending a lot less time marshaling data between different structures and moving it around so that it will fit. You just take it and pass it along. So schemaless, no migrations. Mongo is schemaless, and that means no migration files. There's no replication delays from migrating big tables. There's no special syntax to remember for doing your migrations. An entire aspect to building and maintaining an application is just gone. Many of the issues we have at work with MySQL have to deal with updating the schema. Most of our downtime is for schema updates. Our replication delays are because of schema updates. Working late for engineers are because of schema updates. And the most often reviewed and debated code for all of those reasons is schema updates. But schemas also provide some benefit. They are there to help define what the data will look like. Otherwise, you can just stick anything into the database anywhere, and you have no idea who's putting what in. So there are solutions to help out with that with Mongo. One of them is called Mongoose, and we'll talk about that in just a second. So using the Node.js Mongo driver directly in your application would be rather like using just JDBC to interact with the relational database directly, or handwriting SQL queries in Ruby. While there are times that you wanna drop down to those low levels and do that, we can learn from the successes of these other technologies and how they've abstracted away the raw interaction with the database. In the SQL world, this is done with an ORM, an object relational mapping. In Mongo, this can be done with an ODM, which is object document mapping, of which Mongoose is one. Mongoose also has the added benefit that in addition to just interacting with the database, you can use Mongoose to define your schema and require any documents being inserted into the database will have to follow the schema that you've set up. So we talked about not having a schema on the database being a benefit, but then why ever would you wanna write your schema in the application? Well, you're now moving a lot of your code that has to be deployed out to the database that is causing all these database issues separate from your application. And you're taking it and applying it into the application layer. So you no longer have the time, your migration and deployments to be at the same time, you can just deploy your application code. It also means that you can define your columns or equivalent your columns or records to fit any requirement that you can think of instead of having to go with the predefined column definitions that the database is provided. For example, you could require that phone numbers have to look like phone numbers when they're stored. You not have to convert it to numbers and then back out again or save it as a Varchar or whatever hack there is to store that. You can require that your data have the parentheses around the area code and have the dash. All right, so now let's take a look at an example SPA using Node.js and MongoDB keeping the same data format from the client to the database. So first I'm just going to start up Mongo here and take a look at what databases I have in Mongo. And there's a list of them, but you guys read that? Yeah, all right, the one we care about is SPA. I'm going to use SPA and look at the collections which are Mongo's equivalent of tables. Got a cars, model names, and users. The one we're going to use is users. So we're going to read dbusers.find. This is the equivalent of select star from users. And then you can even take it and say we want to make it look nice. All right, there we go. So here's our users stored in documents and JSON documents in the database. I've got the ID, the name, username, address, and password. Take and put up the Node server. All right, it's listening. So there's our users and just this simple application here. I'm going to refresh the page. And you can see it made this Ajax call to list all the users. And it came back in exactly the same format as was stored in the Mongo database. Name, username, address, password, and two JSON documents. It's just passed on up here to the front end the same way. So if you want to take a look at a user, it made an Ajax call to users read and passed in the user ID, that's the Mongo ID. And you go to database, a little bit long query, so I'm just going to copy it. And make the same query, you just get the same JSON document. All it's doing is taking the JSON document directly out of the database and passing it up to the UI. So let's take a look at the code in the middle tier that makes this possible. So here's the code for the middle tier. This is what Node.js application looks like. Is there anybody here who's familiar with Node.js has used it in the past? Nope, all right. So all we're doing here is requiring a bunch of JavaScript files. These are basically the equivalent of the script tag on the client side. And then we're passing in some configurations. Oh, here's where we use Mongo's to connect to Mongo database. And here we're defining a user object or a user model. These down here are routes that are getting called that are going to match the URL that gets passed in up here or that gets passed in here. So this call is made to slash user slash read slash ID. And so users read ID gets called. And actually let me step into the user model here. So this is Mongo's and how it defines a schema for MongoDB. You just require the Mongoose script and call Mongoose.schema and pass in adjacent structure that defines how the schema is supposed to look. In this case, I just defined a bunch of strings. But what that does is it constrains so that if you try to save a user object and it has additional attributes, it just doesn't save them. So they don't get persisted to the database. So once you've got your Mongoose schema, you can then use Mongoose to define a model based off that schema called user and then we export it back to here. So that brings us back down to the route we have defined where we're just taking that user object. We're calling find by ID, which is a Mongoose built-in method that expects an ID and a callback function. The callback function gets called once Mongo responds and it gives you, if there's an error, it's the first parameter and if it's a success, it takes the document from Mongo and sends it back to you. Then we take the document response from Mongo and response.send, we just send it directly off to the client without doing any manipulation to it. Any questions there? Can I define? So, well, Mongo automatically puts ID fields on, well, underscore ID on all of its document. So you probably could define ID colon and then using Mongo, you can define how you want your IDs to look. In this case, I just went with the default ID formatting for Mongo, which is that long string. Any other questions? Okay. Let's see. I'm looking to use our back to JS. Mongoose is a module that you can add on to Node.js. It's built and maintained by a separate company. I think it's 0.8. What's that? It's under 1.0. Yeah, it's under 1.0 still. All right, so let's take a look at the client side to see what we're doing with that JSON document once it hits the client. So this is just jQuery here to line 10 here means on page load. We're gonna set a click event on all the elements with the class of name. That's these guys here, just the names. Now, when that click event is called, we're going to call the function show user, passing in the attribute from that node of the user ID attribute, which is this guy here. Let's just print it out as an attribute on that element. Show user takes that ID, makes an Ajax call to user slash read, and when he gets a response, it passes that response through this template function and then puts it directly into the HTML of the page. This template function, all we do is access those attributes that are passed back out of Mongo directly and build a table around them. And then we take that table here and just dot HTML, just sticks it into the page in the div with the ID of user. Okay, any questions about that? All right, so next I'm gonna show you something that I think is pretty cool and it's something that you can do with Node.js, particularly easy, which is using web sockets. Web sockets will end up locking up Apache-based applications because Apache uses threads instead of an event-based processing queue. Node.js is event-based processing by default. So when somebody makes a connection to it, if that connection is held open, it doesn't take Node much, if any, effort to maintain that connection. It's just listening for an event. And when an event comes down, then it actually goes and starts doing something. So we're gonna use the same application as before, but this time we'll add Socket.io node module to manage our web sockets and connections. Socket.io also brings backwards compatibility to browsers that haven't implemented web sockets and never will, like IE6. So let me just go back over here, JS. So now you can see in the log here that since we've got Socket.io on here, it logs out that, yes, Socket.io has started. Okay, so now, a little bit. Okay, sorry, I started the wrong application there. All right, so it started up. Let's open up Chrome, have it running, and let's open up Safari, same application. Now, what I'm gonna do is gonna add a user and you're gonna see Socket.io is going to push that new user to the other browsers who are just sitting there with an open web sockets connection, and they're not doing any polling, they're just sitting there with an open connection. So I'm gonna add user, user, and it just instantly updates on the other browsers. Go and delete, instantly deletes on the other browsers. So let me now show you how we've accomplished that. Let's see these guys down. So here's the same application we had before, but this time we've required the Socket.io and we've told it to listen to the server. Then we've got variable current users set to an array, and then every 100 milliseconds, we're telling it to call the watchMongo function. WatchMongo uses the same user object that we had before and does user.find and sorts all the results by name and ascending order, executes them, and then compares the length of the response with the length of current users. So if you've added or removed users, it's going to execute, it's gonna set current users to users to record the change, and then it's going to io.sockets.amit users. And that's just the syntax you use to io to push information up to the browser. Then on the client side, that's it. You've got this io.connect on users, and it tells it here this is the name of the socket to listen to, the user socket, and it was defined here. So we're emitting and reading from the same place. And then, oh, on app.js, this users, this is the same document that Mongo passed to us from the last time, so users.find, it's the response from that. And it's just getting pushed up via the socket instead of via an Ajax request. It comes through here, and then is passed through reload user list, which just writes out our user list using the same JSON document passed to us from Mongo. Okay, now I wanna have a little bit of fun with this and see if we can crash it. What I'm going to do is look and see my IP address on here, 215, and take my web application and tell it to listen on port 3000 on 215. I'm going to stop the application, run it again. Let me close Firefox and Safari and go there. All right, now guys that have laptops open, go to this address here and start adding users. It, yes. Oh, I'm sorry, IO, that comes with a script tag that you'll enter, it comes with a script tag from Socket IO, so it's a socket, it's not a native JavaScript thing, it comes with Socket IO. There we go, Peters added one. Well, as you can see, don't have to refresh anything, everybody's connecting to the Node.js server, adding things to MongoDB. I'm pulling MongoDB with Node.js. Yeah, I'm pulling, oh, is it? Okay, yeah, I don't think. Yeah, or if you could have MongoDB emit something saying I've updated it or, yeah. All right, well, it looks like my MacBook Air can handle this traffic just fine. All right, so that's all the time I have. So this is kind of just a little taste of this talk. I'm gonna continue with a couple of upcoming meetups. One at the Silicon Valley NoSQL Meetup Group on September 6th in Sunnyvale, and another one with the San Francisco MongoDB User Group in San Francisco on September 18th. You can check my blog at jsjoshing.com. And it has the updates and information about where I'll be speaking. And so what I'll additionally be showing there is how you can use Mongo to enforce other interesting constraints, like it's so you don't have to do just strings or you want it built into the database, but you can actually do anything, you can do a reject expression for, think about in order to constrain data being put into the database. And then I'm going to show the rest of the cred operations. We did read and list here, but I'll show you how to do updates, deletes, creates. And it's pretty much just the same kind of length of code that was there. And then we'll go into more detail on socket.io and how we used it to interact with MongoDB. Yep, questions? I haven't put it up there yet. I'll probably put it up on GitHub and on jsjoshing.com I'll let people know. Any other questions? Good question. So Google will actually spider single page applications if you use a hash bang when you're recording the path of the URL. So in the book we explain how we use a, drive the updates of a single page application through updating the URL and specifically the hash tag. So it's this portion. So a lot of times you'll see in single page applications what it'll do is they'll update something on the page and then they'll update the URL afterwards. But what you wanna do is have the portion after the URL actually execute the event that updates the page. So that way when you pass it around to somebody in email or your book market, the single page application will come and show this page and then it will execute what's in the hash tag. Google, when you have this hash bang here instead of just the hash tag, you're telling Google I want you to spider this. Go ahead and execute this JavaScript, change the stuff on, well, doesn't execute the JavaScript. You on the server side have to accept this request and return a page that you get to format how you want to. Right, but you get the additional advantage of you get to tailor that page to exactly what you want it to look like for Google. So all you do is you dump in one image in there, whatever the top image you want to show on Google is and then a bunch of SEO optimized text. And then when somebody goes to the Google search engine and clicks on that link, it brings them to this page with the hash tag, with the hash bang and it actually opens what you, what the person should be seeing instead of Google. I'm sorry, can you ask again? So sometimes I mean it's easy to see on how it's scale, I think it's getting to the point where it scales quite well. We've got, especially if you're using Mongo as your back end and you can use Mongoose as your ODM because then you can define models like you normally could but if you're using a relational database, I don't know of an ORM personally that works as well as like ActiveRecord does for Ruby on Rails. So you're back to writing a lot of your SQL code by hand. So it's just like if you didn't have hibernate or I betus for Java and you just had to write raw SQL queries. So Node.js is maturing as a language and in some places it works very well and I think one of those is with MongoDB and Mongoose. For Node.js, the LinkedIn mobile app. The LinkedIn's mobile app is built in Node.js. LinkedIn? LinkedIn? Yeah. LinkedIn. So you mean it's written in Node.js? Yeah, they're mobile applications written entirely in Node.js. Uh huh. Ha ha ha. Yup. Yup. Did it for me. We're going to do 100 developer rich UI applications. Uh huh. We're going to push back and get our, from our Java developers, there's a Clips and our .NET developer where you use Visual Studio's development tools to bugging and also to bridge this up and find available in Java search right now. Uh huh. And you kind of speak to how those things are maturing for a gap to learn. Sure, there's an IDE called WebStorms which is new that is proven very popular. But of course it being a newer environment, it's not going to be as well developed to say Clips or IntelliJ are. But I found I don't need it. Like when I'm programming in Java, I absolutely need an IDE to help autocomplete and tell me what all these things are and be able to follow code around. And I just haven't needed that myself when working with it. And it's definitely a young ecosystem but I think the ecosystem has been ramping up rather quickly. Even quicker than Ruby on Rails ecosystem is ramped up. And that's because of the popularity of being able to develop one language across the entire stack. Eclipse and IntelliJ for example are very good at developing in Java but even with their plugins it really sucks developing JavaScript in them. So even they only handle a portion of what you're writing and talking about. For user interfaces, well then you're reliant on the user interfaces that are the code that's written for the client. So then you're talking about there's jQuery UI, jQuery mobile, you could do dojo or extjs on the front end at work for our enterprise application or using extjs because it has widgets for everything you can think of. So you just have to be selective about what you're going to be developing it and on the client side. All right, any more questions? All right, great. Thanks for coming everyone. Thank you.