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:
String
true
true
createdAt
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:
ObjectId
Tag
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.js
Update 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
name
GET
/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.js
Create 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.js
Don'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')
])