mari tang
Posted on March 1, 2019
warnings
Note that this is strictly a hello-world kind of exercise. In a real environment, you'd probably have some more security configuration on your database. This creates an entirely unprotected database that can be read or modified by anyone who connects to it. With that said, here's a guide for how to go from a basic understanding of NodeJS to reading from / writing to a mongoDB database.
getting MongoDB's process running
Here's a big-picture breakdown of MongoDB. MongoDB is made up of databases, which have collections inside of them, which contain multiple documents. In mongoose
, the documents are essentially javascript objects that follow a pattern that follows a schema that we define.
In order to get anything done in our database, we need to have a process running that will allow users to access it. In order to do this, you want to install MongoDB, and then run mongod
. You may have errors regarding permissions in /data/db. This is because /data/db is a protected folder, and you may need to run mongod as a superuser (which may not be the best- I'm not clear on the security implications here). it looks like this: sudo mongod
. (Leave this window open so that the process can continue to run, and don't touch it unless you want to shut down your database.)
When you type sudo mongod
, part of what shows up on your console should look like this: MongoDB starting : pid=2265 port=27017 dbpath=/data/db
. The port for a mongoDB instance is 27017 by default, but it will always be printed when you start up mongod. just look for port. This will be important later.
Now, your database will be stored at /data/db, though not in any format that seems to be readable to us. We can access our databases through the mongo shell, which we'll get into later.
Creating and configuring our NodeJS server
Now, we can finally get into creating and configuring our server.
First, we have to npm init
in our desired directory to create our server, then we'll npm install mongodb
and npm install mongoose
as a bare minimum for a proof of concept / hello world-type server.
We'll create a file called server.js
in our project folder that we'll run using node server.js
. This server.js
will contain all of the logic that our server follows.
Our goal is to create a database, write to it, and read from it, all from our server. Here's a quick roadmap of how we'll do it:
- import mongoose
- connect to our database
- create a schema object using mongoose.Schema() constructor and an object that defines the criteria (keys, datatype, etc) for our data
- create a model by using mongoose.connect(), with the name of our collection, and the schema object we just created
- use the model as a constructor function to generate a mongoDB document object
- the mongoDB document object that we have returned will have a method called save(), which will allow us to save it to the database.
- If we want to find our data afterwards, our model (not the document), has a method called 'find()'. Note that our database methods are asynchronous.
step 1: import mongoose inside of our server file.
//in server.js
const mongoose = require('mongoose')
Next, let's connect to our database. Once again, if you've run mongod
in your CLI, it should print out some information, including a port number (27017 by default). If you're connecting to a remote host, they'll provide the information required to log in.
step 2: connect to db
You'll connect at mongodb://localhost:<portnumber>/<databasename>
, and it'll look like this:
//in server.js
const mongoose = require('mongoose')
mongoose.connect('mongodb://localhost:27017/test', {useNewUrlParser: true});
You may have noticed that we've added 'test' to the end of mongodb://localhost:27017/test
. test
is the name that we're choosing to call our database. We haven't created this database yet, but it doesn't matter, because in MongoDB, it will be created when we start storing documents on it.
Now that this connection has been established, we can start creating schemas, models, and documents. This starts with our mongoose.schema
method, which is a constructor function that lives on mongoose
Let's store our mongoose.schema
on a const, so we can access it more easily.
step 2.5: save our schema method
//in server.js
const mongoose = require('mongoose')
mongoose.connect('mongodb://localhost:27017/test', {useNewUrlParser: true});
const Schema = mongoose.Schema
mongoose.Schema is a constructor that takes an object.
The object that we give to the constructor is a 'schema' that represents the structure of our data, with key/value pairs.
Step 3: create a schema
In our example code, our schema will be called exampleSchema.
//in server.js
const mongoose = require('mongoose')
mongoose.connect('mongodb://localhost:27017/test', {useNewUrlParser: true});
const Schema = mongoose.Schema
const exampleSchema = new Schema({
someKeyName: {type: String, required: true, unique:true},
someOtherKeyName: {type: Number, required: false, unique:false}
})
What this means is that each object in our collection is going to have two keys: someKeyName and someOtherKeyName. The value stored on someKeyName will have a type of String
, will be required, and will be unique. The value stored on someOtherKeyName will need to be a Number
, and is neither required nor unique (I'm not sure what unique is).
Step 4: Create a Model
Next, we'll create something called a 'model', which will link our schema to our collection.
we invoke mongoose.model()
, which takes two arguments, one of which is a string that is the name of our collection, the other of which is the new object we created. Once again, it doesn't matter that we haven't already created a collection. MongoDB will create it for us once we try to store data inside of it.
//in server.js
const mongoose = require('mongoose')
mongoose.connect('mongodb://localhost:27017/test', {useNewUrlParser: true});
const Schema = mongoose.Schema
const exampleSchema = new Schema({
someKeyName: {type: String, required: true, unique: true} ,
someOtherKeyName: {type: Number, required: false, unique:false}
})
const newModel = mongoose.model('collectionName', exampleSchema)
that step links the schema with a name for your collection (which produces a 'model'). This model is actually a constructor function, which creates 'document' objects.
step 5: Create a document
In order to do this, we take our model (newModel
), and give it an object that holds all of the data that we want to go in a single document.
//in server.js
const mongoose = require('mongoose')
mongoose.connect('mongodb://localhost:27017/test', {useNewUrlParser: true});
const Schema = mongoose.Schema
const exampleSchema = new Schema({
someKeyName: {type: String, required: true, unique: true} ,
someOtherKeyName: {type: Number, required: false, unique:false}
})
const newModel = mongoose.model('collectionName', exampleSchema)
const newDocument = newModel({someKeyName: 'hi', someOtherKeyName: 12345})
step 6: save the document
Now the newDocument
object exists, we have access to methods on it. One of these is a save
method. It does exactly what you think it does.
//in server.js
const mongoose = require('mongoose')
mongoose.connect('mongodb://localhost:27017/test', {useNewUrlParser: true});
const Schema = mongoose.Schema
const exampleSchema = new Schema({
someKeyName: {type: String, required: true, unique: true} ,
someOtherKeyName: {type: Number, required: false, unique:false}
})
const newModel = mongoose.model('collectionName', exampleSchema)
const newDocument = newModel({someKeyName: 'hi', someOtherKeyName: 12345})
newDocument.save()
Congrats! you just used mongoose to create and write to a database.
Let's go ahead and verify that the document exists in our collection. You can do this outside of node through the next sequence of commands:
mongo
will spin up the mongo command line.
inside of the mongo command line interface, you can type the following:
show dbs
will show you a list of dbs. You should see test
on the list.
use test
will log you into your test
database.
show collections
will show you the collections in your test
database. You should see a collectionName
collection printed out.
db.collectionName.find()
will do an empty query on the collectionName
database, which should return every document within that collection.
you should see something like this: { "_id" : ObjectId("5c78204590796a1c74a20b11"), "someKeyName" : "hi", "someOtherKeyName" : 1234, "__v" : 0 }
There's your database entry!
Of course, this is not so useful for us. Given that we're trying to work with our database from inside of nodeJS, we need to be able to read from our database within our server file.
Back inside of the server, let's invoke a 'find' on our model in order to read from the database.
//in server.js
const mongoose = require('mongoose')
mongoose.connect('mongodb://localhost:27017/test', {useNewUrlParser: true});
const Schema = mongoose.Schema
const exampleSchema = new Schema({
someKeyName: {type: String, required: true, unique: true} ,
someOtherKeyName: {type: Boolean, required: false, unique:false}
})
const newModel = mongoose.model('collectionName', exampleSchema)
newModel.find({somekeyname:'hi'}, (err,results)=>{
console.log(results)
})
This may require a bit of explanation. The first argument is fairly clear. it's an object with key/value pairs that we're searching for. The second argument (called a callback function) may be a little less obvious.
Basically, we expect newModel.find
to query our database, then do something with the data. What does it do? That's defined in our callback function. If the search fails for some reason, it'll pass in an argument as err
, and if it succeeds, we'll get something in results
.
{someKeyName: "hi"}
should match our entry { "_id" : ObjectId("5c78204590796a1c74a20b11"), "someKeyName" : "hi", "someOtherKeyName" : 1234, "__v" : 0 }
, and we don't have anything else in our database, so our results
variable will evaluate to this: [{ "_id" : ObjectId("5c78204590796a1c74a20b11"), "someKeyName" : "hi", "someOtherKeyName" : 1234, "__v" : 0 }]
. console.log
will simply print that value to our terminal.
Note that, even though it's just one item, the callback for find
returns an array. If it doesn't find anything, it'll just give an empty array []
.
Now that you've got the array of matches, you can start to do stuff with it, whether that's looking up and displaying information, checking authentication, or other such operations!
Posted on March 1, 2019
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.