Still working through the early sections of this mongo course. It’s really less of a course on mongodb, and more of a course on how to use mongoose with nodejs. Not that I really mind, but I would have been pretty upset if I’d bought this course to learn more about actual mongo and not about how to use it with a web application.
Today was talking about dealing with retrieving and deleting records using Mongoose. Both topics are pretty easy, there’s not really much to it. Use the method, provide the criteria to key off of, and boom.
The most interesting thing that came out of the lessons today was dealing with chaining promises. That’s to say, if you’re performing some action that will return a promise, you can chain right into your next promise without having to do any ugly layered call back crap.
Since a lot of my notes are just spread about, I’m just going to be dumping everything again today. Forgive me…
Promises
- Used to help define asynchronous functionality
- You can create a new Promise by using the following syntax:
1
2
3
4
5
6
7
8
9
|
new Promise((resolve, reject) => {
setTimeout(() => {
if (counter>5) {
resolve(counter);
} else {
reject(counter);
}
}, 2000)
})
|
- Note in the above that a Promise has two different inputs, resolve and reject.
- When your Promise has completed running whatever it needs to do, and the call was successful, you’d call the
resolve()
method, passing in any variables you need to return.
- If the promise has failed, such as erroring out, you can call the
reject()
method to return back the failure.
- To handle the actual function in the code, you use the dot notation to chain on to the initial function call:
1
2
3
|
startGame()
.then((count) => alert(`You win!\nYou clicked ${count} times!`))
.catch((count) => alert(`You lost!\nYou only clicked ${count}/5 times!`));
|
- Most libraries already have promises written, we’ll be written the consumers to handle them (at least in this course).
- As long as whatever you’re using returns a promise, you can continue to chain them with
.then()
calls:
1
2
3
4
5
6
7
8
|
it('model instance remove', (done) => {
joe.remove()
.then(() => User.findOne({name: 'Joe'}))
.then((user) => {
assert(user === null);
done();
});
});
|
Basic MongoDB Concepts
- Mongo allows for multiple databases within a single mongo instance
- Each database is made up of n number of collections
- Collections represent a specific kind of data (you wouldn’t typically mix with another collection)
- We’re using Mongoose for Node in this course
- We’re using Mocha for testing against the Node app
User Models
- We create user models (using Mongoose in this case) to define how collections will be structured
- This is where we’re setting what the schema will be for that collection when accessing data within the collection.
- Going to be using
mongoose.Schema
to define the model.
- Schema is created like follows:
1
2
3
|
const UserSchema = new Schema({
name: String
})
|
- Note how the properties of the schema is assigned to a Javascript type of
String
.
- In order to actually create the model (and in turn the collection), the following is required:
1
|
const User = mongoose.model('user', UserSchema);
|
- If the defined collection does not exist in the connected database, it will create it on runtime.
User
above can now be referred to as the User Class
.
User
does NOT represent a single user, it represents the ENTIRE SET of data
- Best practice is to only export the Class name when creating models in projects (making usable in the rest of the application)
- Model classes give access to
find
and findOne
methods.
- criteria is an object with search criteria
Inserting Records
- Start by creating a new instance of your model, complete with the parameters for that model:
1
|
const joe = new User({ name: "Joe" });
|
- Once the instance has been created, you can use the
.save()
method to save it to mongo.
- Save method will return a promise, which can then be used to move on to assertions in Mocha.
- After the new instance is created, Mongoose attaches an
isNew
property to the instance, defaulting to true
- Once this has been saved to the database, this is flipped to false
- As soon as the instance has been created, an
_id
has been assigned
Query Records
- Have two ways to retrieve records:
find
and findone
find
returns array of all matches
findOne
will return back first instance found
- Can’t just use the
_id
for comparison as is, must convert it to a string first.
- Both
find
and findOne
are used the same way. Always need to provide them an object to query off of.
Deleting Records
- Mongoose calls a delete a
remove
- The Model Class supports:
remove()
- remove a bunch of records with some given criteria
findOneAndRemove()
- takes a criteria, only deletes first matching record
findByIdAndRemove()
- looks up an idea
- All three of these are basically the same thing, just different ways of deleting
- An instance of a model only supports the
remove()
method. Only removes the specific instance.
Mocha Tests
- Using mocha for testing automatically gives you access to
describe
function (test case) and it
method (test step).
- Have to make assertions to do the evaluation
assert
package must be imported, not immediately accessible
- Execute tests by running
mocha <test_folder_name>
.
- As an alternative, you can set up an npm start rule to kick it off (same as above).
test_helper
test_helper
file is created to handle things we want to be done related to the test
- In this example we’re using it to establish connection over to mongo
- Inside of
test_helper
you can use a beforeEach()
function to define what needs to be done before each part of the test (such as wiping the db)
- Need to use the
done
callback to pause tests to wait for long running tasks to finish
done
is provided by Mocha
beforeEach
and it
accept the done callback
- Use the
before
function to have the tests wait until the connection has been completed before starting
💚