MongoDB and Mongoose Note
Posted on: September 09, 2023
Find more details in Mongoose Documents.
Set up
- Follow this tutorial to set up a hosted database on MongoDB Atlas.
- Write your MongoDB Atlas database URI inside
.env
file - Import Mongoose in your file e.g.
App.js
asmongoose
- Connect database using the following syntax:
mongoose.connect(<Your URI>, { useNewUrlParser: true, useUnifiedTopology: true });
- Replace
<Your URI>
withprocess.env.<uri_name>
Schema and Model
Each schema maps to a MongoDB collection (i.e. a table in relational database), it defines the shape of the documents (i.e. instances of the objects) within that collection. We use schema to create models, which is like a class object, via mongoose.model(<name>, <schema>)
.
Example
const Schema = mongoose.Schema;const personSchema = new Schema({name: { type: String, required: true },age: Number,favoriteFoods: [String],});let Person = mongoose.model("Person", personSchema);
In the example above, personSchema
has three fields: required string field name
, a optional number field age
and a optional array of strings favoriteFoods
. personSchema
is the created schema defining format of the model and Person
is the model.
When building a schema, there are three options for name validation:
name: Stringname: {type: String}name: {type: String, required: true} //preferred
Detailed introduction can be found in this article.
done()
The done()
function is a callback that tells us that we can proceed after completing an asynchronous operation such as inserting, searching, updating, or deleting. It's following the Node convention, and should be called as done(null, data) on success, or done(err) on error.
const someFunc = function(done) {//... do something (risky) ...if (error) return done(error);done(null, result);};
Create Record
To create and save one record of a model
Create a document/record of a model is like create a object, then save the record using document.save()
.
const createAndSavePerson = (done) => {const p1 = new Person({name: "p1",age: 29,favoriteFoods: ["Pizza", "Sushi"],});p1.save((err, data) => {if (err) return done(err);done(null, data);});};
In the example above, p1
is the document.
To create many records
To create many instances of a model, use Model.create()
that takes an array of objects, then saves them in db.
const createManyPeople = (arrayOfPeople, done) => {Person.create(arrayOfPeople, (err, data) => {if (err) return done(err);done(null, data);});};
Find Record
Find all matching documents
Model.find()
takes a query document (a JSON object), and returns an array of matching documents.
const findPeopleByName = (personName, done) => {Person.find({ name: personName }, (err, data) => {if (err) return done(err);done(null, data);});};
Find a single matching document
Model.findOne()
also takes a query, but only returns a single matching document, even there are multiple matching items. This is useful when searching by unique properties.
const findOneByFood = (food, done) => {Person.findOne({ favoriteFoods: food }, (err, data) => {if (err) return done(err);done(null, data);});};
Find document by ID
When saving a document, MongoDB automatically adds the field _id
, and set it to a unique alphanumeric key. Model.findById(<id>)
is almost equivalent to Model.findOne({_id: <id>})
.
const findPersonById = (personId, done) => {Person.findById(personId, (err, data) => {if (err) return done(err);done(null, data);});};
Chain Search Query Helpers to Narrow Search Results
You can store the query in a variable for later use. This kind of object enables you to build up a query using chaining syntax. The actual db search is executed when you finally chain the method .exec()
.
// This finds people who like burrito, and will sort them by name, limited the results to two documents, and hide their age.const queryChain = (done) => {const foodToSearch = "burrito";Person.find({ favoriteFoods: foodToSearch }).sort({ name: 1 }).limit(2).select({ age: 0 }).exec((err, data) => {if (err) return done(err);done(null, data);});};
Update Record
Find and edit then save
Can use any find method listed above to find the document, then make changes and save the document. This is the classic update method.
const findEditThenSave = (personId, done) => {const foodToAdd = "hamburger";Person.findById({ _id: personId }, (err, person) => {if (err) return done(err);person.favoriteFoods.push(foodToAdd);person.save((err, updatedPerson) => {if (err) return done(err);done(null, updatedPerson);});});};
Find and update
Use Model.findOneAndUpdate()
to find and update document, it takes a query as first arugument to find the document, then update using query in second argument. The third aurgument is for passing options. By default these methods return the unmodified object, so adding { new: true }
as the option will return the updated document.
const findAndUpdate = (personName, done) => {const ageToSet = 20;Person.findOneAndUpdate({ name: personName },{ age: ageToSet },{ new: true },(err, data) => {if (err) return done(err);done(null, data);});};
Remove Record
Delete one document
Both Model.findByIdAndRemove()
and Model.findOneAndRemove
find one matching document and remove it from the database, behaves like the previous update methods.
const removeById = (personId, done) => {Person.findByIdAndRemove(personId, (err, data) => {done(null, data);});};
Delete many documents
Model.remove()
is useful to delete all the documents matching given criteria. This method doesn’t return the deleted document, but a JSON object containing the outcome of the operation, and the number of items affected.
// This removes all documents that has the name Maryconst removeManyPeople = (done) => {const nameToRemove = "Mary";Person.remove({ name: nameToRemove }, (err, data) => {done(null, data);});};