Mongoose supports the creation of methods on both instances of documents and collections of documents (the model).
.statics()
adds static “class” methods to the model..methods()
adds an instance method to documents.
Model Methods — .statics()
For example, in our poetry app we could use .statics()
to create a method named firstAlphabetically
.
const poemSchema = new mongoose.Schema({ ... )} poemSchema.statics.firstAlphabetically = function(callback) { return this.findOne({}).sort('title').exec(callback); }
The method is part of the model, which in this example would return the first document, after sorting the values of the title
path alphabetically.
In order to use the new .firstAlphabetically
method, we would call it inside runWithDatabase()
on the Poem
model like this:
const Poem = mongoose.model('Poem', poemSchema); runWithDatabase(async () => { Poem.create(properties)); const firstAlpha = await Poem.firstAlphabetically(); console.log(`The first poem alphabetically is: ${firstAlpha.title}. It goes like this: ${'\n'} ${firstAlpha.body}`); });
The console.log()
logs the following in the terminal:
The first poem alphabetically is: One of Those Days. It goes like this: My shirt and spirit, are bent inside-out-backwards
Document Methods — .methods()
Instances of a model are documents. Documents have many of their own built-in instance methods. It is also possible to create custom document instance methods. Below, we create a method for our poem example to change the published
path value to true
on any document in the database.
const poemSchema = new mongoose.Schema({ ... )} poemSchema.methods.publish = function(callback) { this.published = true return this.save(); }
.save()
writes the current JavaScript object as a MongoDB document.
Inside runWithDatabase()
we could call .publish()
on a document like this:
const Poem = mongoose.model('Poem', poemSchema); runWithDatabase(async () => { Poem.create(properties)); ... const publishIt = await Poem.findOne({ title: 'Rewrite Reality' }); console.log(publishIt.published) await publishIt.publish(); console.log(`${publishIt.title} has had its publish field changed to ${publishIt.published}`) });
Here we use .findOne
to locate the poem, and then console.log()
the initial publish
value, which is false. We call .publish()
on it and console.log()
again to see that it changed. The output in the terminal for this code would look this:
false Rewrite Reality has had its publish field changed to true
Instructions
Create a static method for your schema called findMostExpensive
and set it equal to a function with a callback argument. Add this in the function’s body:
return this.findOne({}).sort('unitCost').exec(callback);
Create a method for your schema using the syntax magicItemSchema.methods.use
and set it equal to a function with a callback argument. Add this in the function’s body:
this.totalUnits -= this.unitCost; return this.save();
You can add the following code in runWithDatabase()
, then enter node exercise.js
in the terminal to see these methods in action:
const mostExpensive = await MagicItem.findMostExpensive(); console.log(`The most expensive object is the ${mostExpensive.item}`); console.log(`The ${mostExpensive.item} started with ${mostExpensive.totalUnits} charges.`); console.log(`Using ${mostExpensive.item}...`); await mostExpensive.use(); console.log(`The ${mostExpensive.item} has ${mostExpensive.totalUnits} charges left.`);