For this challenge you will clone the Noteful V3 starter and add mongoose
to your Noteful app, create the endpoints for Notes.
- Install Mongoose
- Update the
config.js
file with database connection information - Create a
notesSchema
andNote
model - Seed the database
- Create initial queries in scratch file
- Convert
_id
toid
and remove__v
usingtoObject
- Convert
- Update
server.js
file to connect to the database - Create Notes endpoint
-
Find the
noteful-app-v3
pinned to your Cohort's GitHub Organziation -
Clone the
noteful-app-v3
repo to your local development environment -
Rename the
origin
toupsteam
usinggit remote rename origin upstream
-
On GitHub create a new repo in your Cohort org on Github.
- Name the new repo "[YOUR-NAME]-noteful-v3".
- Do not initialize the repository with a README.
-
On the next page find the section titled …or push an existing repository from the command line and run the two commands
-
Verify your remotes are configured correctly. Enter
git remote -v
, you should see two remotes: one calledorigin
pointing to your repo on GitHub and one namedupstream
pointing Thinkful's repo.
Remember to run
npm install
to install the project dependencies. And create a feature branch for your development work.
To get started, npm install mongoose
and then confirm mongoose
has been saved to the dependencies
property of your package.json
file.
In the config.js
file, add a MONGODB_URI
property like the following:
module.exports = {
PORT: process.env.PORT || 8080,
MONGODB_URI: process.env.MONGODB_URI || 'mongodb://localhost/noteful'
};
NOTE: we are using
MONGODB_URI
here, instead ofDATABASE_URL
mentioned in the curriculum.MONGODB_URI
is used by Heroku's mLab Add-On which minimizes the number of changes when deploying.
Create /models/note.js
file. This is where you will define the Note Schema and create a Note Model. Since this is your first schema, we'll help you along.
You will need to create a schema with the following criteria:
title
a Required String.content
a String
Plus additional date fields to track create and update timestamps
createdAt
Defaults to now when creating a new documentupdatedAt
Saves the current date when updating a field
Add the following to the file:
const mongoose = require('mongoose');
const noteSchema = new mongoose.Schema({
title: { type: String, required: true },
content: String
});
// Add `createdAt` and `updatedAt` fields
noteSchema.set('timestamps', true);
Now, create a Note
model and export it. Remember, the name you pass to the mongoose.model()
method is used to create the lowercase and pluralized collection in Mongo.
module.exports = mongoose.model('Note', noteSchema);
Commit your changes!
Next you need to seed the database with sample data to make development easier. We will not use mongoimport
to seed the database, instead you should create a seed-database utility which uses the Model and Schema you created above. The script connects to the server, drops the database and populates it with your data.
Create a /utils/seed-database.js
file and add the script below. Explore it by adding your own console.log()
.
const mongoose = require('mongoose');
const { MONGODB_URI } = require('../config');
const Note = require('../models/note');
const seedNotes = require('../db/seed/notes');
mongoose.connect(MONGODB_URI)
.then(() => mongoose.connection.db.dropDatabase())
.then(() => Note.insertMany(seedNotes))
.then(results => {
console.info(`Inserted ${results.length} Notes`);
})
.then(() => mongoose.disconnect())
.catch(err => {
console.error(err);
});
Next, run the execute the process by running node ./utils/seed-database.js
and check your database collection to verify the documents were inserted properly.
Commit your changes!
Next, you need to create the CRUD operations in a clean isolated environment. So create a scratch/queries.js
file. To help get started here is a sample .find()
.
const mongoose = require('mongoose');
const { MONGODB_URI } = require('../config');
const Note = require('../models/note');
mongoose.connect(MONGODB_URI)
.then(() => {
const searchTerm = 'lady gaga';
let filter = {};
if (searchTerm) {
filter.title = { $regex: searchTerm };
}
return Note.find(filter).sort({ updatedAt: 'desc' });
})
.then(results => {
console.log(results);
})
.then(() => {
return mongoose.disconnect()
})
.catch(err => {
console.error(`ERROR: ${err.message}`);
console.error(err);
});
Run the scratch file using node ./utils/queries.js
or nodemon ./utils/queries.js
to see the results.
Your Turn!
We've provided the first solution, your challenge is to create the other queries:
- (done) Find/Search for notes using
Note.find
- Find note by id using
Note.findById
- Create a new note using
Note.create
- Update a note by id using
Note.findByIdAndUpdate
- Delete a note by id using
Note.findByIdAndRemove
Commit your changes!
In this mini challenge you'll go back and improve the Note.find()
query.
Using the $or
Operator, update the query to search both the title
and the content
fields.
Notice the output contains an _id
and __v
. Whenever you return a mongoose document instance using console.log(document)
or res.json(document)
, it is converted from a mongoose document object to a standard JSON object. We can use this transformation process convert _id
to id
and remove the superfluous __v
property. Add this statement to your /models/note.js
schema file.
noteSchema.set('toObject', {
virtuals: true, // include built-in virtual `id`
versionKey: false, // remove `__v` version key
transform: (doc, ret) => {
delete ret._id; // delete `_id`
}
});
Rerun queries.js
and you should see the updates.
For more information check out the documentation
Commit your changes!
Update the server.js
file to require mongoose and connect to the database.
Towards the top of the file, add require('mongoose')
.
Next, update the config statement to pull in MONGODB_URI
.
const { PORT, MONGODB_URI } = require('./config');
Lastly, add mongoose.connect(MONGODB_URI)
. You'll want to add it towards the bottom of the page, next to the app.listen
call. This will make it easier to fix when we add integration tests to the mix later.
// Connect to DB and Listen for incoming connections
mongoose.connect(MONGODB_URI)
.then(instance => {
const conn = instance.connections[0];
console.info(`Connected to: mongodb://${conn.host}:${conn.port}/${conn.name}`);
})
.catch(err => {
console.error(`ERROR: ${err.message}`);
console.error('\n === Did you remember to start `mongod`? === \n');
console.error(err);
});
app.listen(PORT, function () {
console.info(`Server listening on ${this.address().port}`);
}).on('error', err => {
console.error(err);
});
Commit your changes!
This is the main hurdle for this challenge.
Update the /routes/notes.js
file with the queries above. The /routes/notes.js
file contains skeleton endpoints which you need to fill in using the queries you created above.
- Find All notes (search by title) using
Note.find
- Find Note by id using
Note.findById
- Create a new note using
Note.create
- Update a note by id using
Note.findByIdAndUpdate
- Delete a note by id using
Note.findByIdAndRemove
Once you are happy with your solution. Checkout master
and merge your feature branch and push your changes to Github.
You can view an example solution and compare the differences between branches
- Solution: You can find the example solution in the
solution/01-notes
branch in the upstream repo.