Challenge 15: Mongo(ose) Relationships II
In this challenge, you will add Tags to the Noteful app, populate the notes with tags, create routes and tests for the tags and update the routes and test for the notes.
server.js to mount tags routerSince you created a similar schema and model for Notes and Folders we will keep the instructions brief.
Create a /models/tags.js file and create a tagsSchema with the following specs:
/models/tags.js file for the Schema and Model.tagSchema and define a name field with the following criteria:
StringtruetruecreatedAt and updatedAt using the Mongoose timestamps optiontoObject option to transform the doc:
virtuals like id to show in the output__v version key_id from the return objectTag model using the tagSchema and export itNext you will create Tags seed data and update Notes seed data with tags.
/db/seed/tags.json file[
{
"_id": "222222222222222222222200",
"name": "breed"
},
{
"_id": "222222222222222222222201",
"name": "hybrid"
},
{
"_id": "222222222222222222222202",
"name": "domestic"
},
{
"_id": "222222222222222222222203",
"name": "feral"
}
]
Now that you have defined a Tag Schema and Model, you can add a tags field to the Notes Schema.
In /models/note.js, update the noteSchema as follows:
tags field:
ObjectIdTag modeltags: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Tag' }],
Let's update the notes.json. Below is a sample note with its tags set to the _id for foo, bar, and baz. Update the sample data in your seed data file with tags info
{
"_id": "000000000000000000000003",
"title": "7 things lady gaga has in common with cats",
"content": "Posuere sollicitudin aliquam ultrices sagittis orci a. Feugiat sed lectus vestibulum mattis ullamcorper velit. Odio pellentesque diam volutpat commodo sed egestas egestas fringilla. Velit egestas dui id ornare arcu odio. Molestie at elementum eu facilisis sed odio morbi. Tempor nec feugiat nisl pretium. At tempor commodo ullamcorper a lacus. Egestas dui id ornare arcu odio. Id cursus metus aliquam eleifend. Vitae sapien pellentesque habitant morbi tristique. Dis parturient montes nascetur ridiculus. Egestas egestas fringilla phasellus faucibus scelerisque eleifend. Aliquam faucibus purus in massa tempor nec feugiat nisl.",
"folderId": "111111111111111111111101",
"tags": ["222222222222222222222200", "222222222222222222222201", "222222222222222222222202"]
},
seed-database.jsUpdate the /utils/seed-database.js file to insert tags and create an index. The index Tag.createIndexes() call tells mongo to create an index immediately which is used enforce the unique rule on Tag names.
Below is a simple and reliable way to seed the database and trigger indexing. Update your /utils/seed-database.js file to require the Tag model and seed data. And then update it to insert Tags and create an index as shown below.
// ... REMOVED FOR BREVITY
mongoose.connect(MONGODB_URI)
.then(() => mongoose.connection.db.dropDatabase())
.then(() => {
return Promise.all([
Note.insertMany(seedNotes),
Folder.insertMany(seedFolders),
Tag.insertMany(seedTags),
Folder.createIndexes(),
Tag.createIndexes()
]);
})
// ... REMOVED FOR BREVITY
Confirm the seed process worked correctly by verifying the data using Mongo shell or your favorite database GUI.
Your next challenge is to create Folder endpoints and integration tests.
Create a new /routes/tags.js file to hold the endpoints and mount it on server.js. In the file, create the following CRUD endpoints.
GET all /tags
nameGET /tags by id
POST /tags to create a new tag
name fieldlocation header and a 201 statusduplicate key error with code 11000 and responds with a helpful error messagePUT /tags by id to update a tag
name fieldduplicate key error with code 11000 and responds with a helpful error messageDELETE /tags by id deletes the tag AND removes it from the notes collection
$pull, remove the tag from the tags array in the notes collection./routes/notes.js endpointsGET all /notes
tags to the response.populate() to populate the tags arraytagId and conditionally add it to the database query filterGET /notes by id
tags to the response.populate() to populate the tags arrayPOST /notes
tags from request bodyObjectId and, if necessary, return a user-friendly response with a 400 statustags along with the other note fieldsPUT /notes
tags from request bodyObjectId and, if necessary, return a user-friendly response with a 400 statustags along with the other note fieldsDELETE /notes
/test/tags.jsCreate a /test/tags.js file, the basic structure in similar to /test/folders.js. Update the require statements and the Mocha life-cycle hooks to use Tag models and tags seed data.
Create tests to verify the functionality of the /tags endpoints. As your work through the tests, check the code coverage for clues on which aspects of your code you have validated and which still needs tests.
/test/notes.jsDon't forget to update /test/notes.js. You added new features to these endpoints earlier and that functionality needs to be tested to ensure it continues to work properly.
Check your code coverage. Are there any lines of code which are not covered by tests? Create tests for any outstanding features.
Finally, uncomment the tags search on /public/index.js.
Promise.all([
api.search('/api/notes'),
api.search('/api/folders'),
api.search('/api/tags')
])