Retrieve Data Using Queries - AdarshMaurya/mongodb-and-mogoose-for-node-getting-started GitHub Wiki
Introduction
Welcome to this module on retrieving data from MongoDB using Mongoose queries. In the previous module, we saw how to save a document to MongoDB using the models save method.
- Retrieve documents
- Model methods
- find
- findById
- findOne
- where
Updating and removing documents
In this module, we will be looking at the various methods to retrieve and update document. We will start by looking at the model methods find, findById, findOne, and where. We will then examine some of the methods used to update and remove documents from a MongoDB collection.
Documents and Helper Methods
You learned earlier that a Mongoose document is an instance of a model and that this Mongoose document directly represents the document saved in a MongoDB collection. In this clip, let's examine some of the model methods available to us and start with those used to retrieve documents from MongoDB including find, findOne, findById, and where.
Let's start with the find method and some examples of how to use that. With each of these examples, we will start by requiring a model file so that we can gain access to that particular model's helper methods. In this first example, we're bringing in the standup.js model file. Also, with each example in this module, you'll notice at the top right of the page the method parameters available to each and whether they're required or not.
FIND
const Standup = require('../models/standup.js')
Parameters
conditions required
[projection] optional
[option] optional
[callback] optional
We will not cover each parameter or possible option, but we will go through enough examples that I believe you'll get the general idea of how to utilize each of the various query methods that we will cover here.
In this first example, we're simply calling the find method with an empty conditions object and no optional parameters. What this will do is return all of the documents within the collection associated with this model, which as a reminder, is defined in the schema.
const Standup = require('../models/standup.js')
// No callback... Deferred execution
let query = Standup.find({});
query.exec(function(err, results){...});
In our case, this is our standup collection of documents. When a callback is missing, as it is in this example, find will return a query object, which we are storing in the query variable. This query is not executed against the MongoDB database, at least not until you tell it to as shown here.
const Standup = require('../models/standup.js')
// No callback... Deferred execution
let query = Standup.find({});
query.exec(function(err, results){...});
// With callback... Execute query immediately
Standup.find({},function(err, results){
// handle the error... or results here
});
In this next example, we are passing in a callback function, and while the find method still returns a query, it is passed to the callback and immediately executed. Callbacks have the signature of first passing in an err and then the results, which once again here, happens to be all of the documents within the standup collection.
const Standup = require('../models/standup.js')
// No callback... Deferred execution
let query = Standup.find({});
query.exec(function(err, results){...});
// With callback... Execute query immediately
Standup.find({},function(err, results){
// handle the error... or results here
});
// With callback and query conditions
Standup.find({memberName: 'David'}, function(err, results){
// handle the error...or results here
});
This example shows us passing in some query conditions now to narrow down our results a little.
In SQL terms, this would read something like SELECT * FROM Standup WHERE MemberName = David
. All documents found to match this query condition object will be returned in the results object. And if we have any errors, those will be returned in err. You may not always want to return all available fields found in a document.
const Standup = require('../models/standup.js');
// No callback... Deferred execution
let query = Standup.find({});
query.exec(function(err, results){...});
// With callback... Executes query immediately
Standup.find({}, function(err, results){
//handle the error...Or results here
});
// With callback and query conditions
Standup.find({memberName: 'David'}, function(err, results){
// handle the error...Or results here
});
// Limit the returned fields...
Standup.find({memberName: 'Mary'}, 'memberName impediment', function(err, results){
// handle the error...Or results here
});
In this last example, you can see here that a string representing the fields we wish to return are listed, memberName and impediment. Other fields within the document will not be returned in these results.
Next, let's look at the findOne method, which as the name would suggest, returns only one document.
Model.findOne(...)
Parameters
conditions required
[projection] optional
[options] optional
[callback] optional
const Standup = require('../models/standup.js');
// With callback and query conditions
Standup.findOne({memberName: 'David'}, function(err, results){
// handle the returned docs and/or errors
});
This first example shows passing in a conditions query object asking for a memberName of David. The single first result found will be passed into the results of the callback function. As with the find method example we just looked at, you may not always want to return all available fields found in a document.
const Standup = require('../models/standup.js');
// With callback and query conditions
Standup.findOne({memberName: 'David'}, function(err, results){
// handle the returned docs and/or errors
});
// Limit the returned fields...
STandup.findOne({memberName: 'Mary'}, 'memberName impediment', function(err, results){
// handle the error...Or results here
});
So here again, in this example, we're passing in a string that represents only the fields we want returned, memberName and impediment.
Model.findById(...)
Parameters
id required
[projection] optional
[options] optional
[callback] optional
const Standup = require('../models/standup.js');
// No callback...Deferred execution
let query = Standup.findById(id);
query.exec(function(err, results){
// handle the error... Or results here
});
// Same as above - using chained method calls
Standup.findById(id).exec(function(err, results){
// handle the error... Or results here
});
While find and findOne are very useful and will be used a lot within your applications, it's nice to also ask for a specific document by its unique id value. That's what the findById method does for us if that wasn't obvious by the name of the method alone. You'll also notice that the findById method parameters have changes slightly. There are no conditions to pass in because the only query condition is the id, nothing more. Each of these find methods can be chained together as shown here. FindById also returns a query object, which has an execute method, which takes in a callback function and so forth.
const Standup = require('../models/standup.js');
// No callback...Deferred execution
let query = Standup.findById(id);
query.exec(function(err, results){
// handle the error... Or results here
});
// Same as above - using chained method calls
Standup.findById(id).exec(function(err, results){
// handle the error... Or results here
});
// Return every field EXCEPT impediment
let query = Standup.findById(id, '-impediment');
This last example shows how you can ask for every field within a document to be returned, but the impediments field. Notice the minus sign of the beginning of the string here?
Comparison Query Operators
$gt greater than
$gte greater than or equal to
$in exists in
$lt less than
$lte less than or equal to
$ne not equal to
$nin does not exist
Note: These are the same as what is found in MongoDB
Before we talk about our last query method, where, let's talk a little about comparison query operators. Those include greater than, greater than or equal to, exists in, less than, less than or equal to, not equal to, does not exist.
// Example: find customers with discount >=10% ...
Customer.find({discount:{$get:10}}, function(err, results){
if(err) throws err;
console.log(results);
});
In this code example, which illustrates the use of the greater than or equal to comparison operator, we're asking to find customer documents where the discount value is greater than or equal to 10. In some of the previous examples, you may have noticed that we were asking for a member name and then passing in a string. Here we're passing in an object that includes a comparison operator, or any number of comparison operators can be used. Simply place a comma between each pair.
Model.where(...)
Parameters
path required
[val] optional
const Customer = require('../models/customer.js');
Customer.find(discount:{$gte:10, $lt: 20}, function(err, results){
if(err) throw err;
console.log(results);
});
Customer.where('discount').gte(10).lt(20).exec(function(err, results){
if (err) throws err;
console.log(results);
});
Let's take the previous comparison query operator example and see what that would look like if we were using the where method. As a comparison, let's take a look at the find method again. It's very similar. The where method also returns a query object that we can simply apply the greater than or equal to and less than query comparison operators to and then execute the query immediately via the callback function.
Model.where(...)
Parameters
path required
[val] optional
Looking at the parameters here, the first required parameter is path. What exactly does that mean? If we compare the first find example to the where query example, you can see that the path is simply the name of the document field we are querying against. This could also be a nested path, say for example, discount.amount or discount.percentage.
const Customer = require('../models/customer.js');
Customer.find(discount:{$gte:10, $lt: 20}, function(err, results){
if(err) throw err;
console.log(results);
});
Customer.where('discount').gte(10).lt(20).exec(function(err, results){
if (err) throws err;
console.log(results);
});
// Chain where methods together...
Customer.where('discount').gte(10).lt(20)
.where('zipCode', '1234')
.exec(function(err, results){
if(err) throw err;
console.log(results);
});
Because queries are chainable, we can continue adding on where methods as shown here. In this example we're also supplying the optional val, or value argument, asking for a zipCode of 12345.
Updating and Removing Documents
Now that we understand how to retrieve documents from MongoDB through Mongoose, let's talk about how to update and remove these documents as well.
Standup.findById(id).exec(function(err, doc){
//handle any errors
if(err) return errorHandler(err);
// update the found document
doc.impediment('None');
doc.save(function(err){
if(err) return errorHandler(err);
console.log('Document updated');
});
});
When thinking about updating an existing document, one approach we could take would be to simply perform a find, like this findById example, update the resulting document, and then save those updates; however, let's think about what is going on with this example for just a moment.
We first have to find a document, and that's one call to the database. Then we have to make a second call to pass in the updated document, and that may be exactly what you need to do in some cases, but most of the time it will not be.
So let's look and see if there is a different way to do these updates, maybe one that only calls the database once. Much like the model query methods we looked at in the previous clip, a Mongoose model also has methods to help us update and delete documents. Here are some of the model methods we will examine in this clip.
Model Methods
- updateOne
- updateMany
- deleteOne
- deleteMany
- findByIdAndUpdate
- findByIdAndDelete
UpdateOne, which updates one document; updateMany for those times you want to update a number of documents with the same data; deleteOne to remove or delete a single document from MongoDB; and deleteMany, as the name would imply, used to delete multiple documents that match the given query conditions object. We'll also look at findByIdAndUpdate, as well as findByIdAndDelete.
Let's start by looking at the model update methods. And first up is updateOne.
Model.updateOne(...)
Parameters
conditons required
doc required
[options] optional
[callback] optional
const Standup = require('../models/standup.js');
const qry = { memberName: 'Marry' };
const update = { memberName: 'Mary' };
// Only updates the first document matching query criteria
Standup.updateOne(qry, update, function(err, rawResponse){
// Handle error or raw results here...
});
As with the previous examples we looked at, the parameters for this model method are listed above. For updateOne, both the query conditions and doc parameters are required. The standup model has been pulled in, and next, we set up the query condition object, asking for a standup document that has a memberName of Marry. Next, we set up the update document, what we wish the document found using the conditioning query to be updated to. Now we pass into the standup model's updateOne method, the condition query, and update document from above. There may be more than one document that matches a query condition, but with updateOne, it only updates the first one found. Since we have a callback function in this example, it will get executed immediately and any error will be passed back into the err object, and the full response from MongoDB will be passed into raw response.
In a number of the find and update examples we have looked at so far, you probably noticed most have an optional options parameter that can be passed in. For more information on which options are available for the particular model method you may be working with, please take a look at the Mongoose API documentation and look look for Query-setOptions found at this URL. Not all options are applicable to all methods.
We just looked at how to update one document. Now let's examine the model method used to update a batch of documents that match our query conditions, updateMany.
Model.updateMany(...)
Parameters
conditions required
doc required
[options] optional
[callback] optional
const Standup = require('../models/standup.js');
const qry = {impediment: ''};
const update = {impediment: 'None'};
// update all document that match query
Standup.updateMany(qry, update, function(err, rawResponse){
// Handle error or raw results here...
});
// same just using inline parameter objects
Standup.updateMany(
{impediment: ''},
{impediment: 'None'},
function(err, rawResponse){
// Handle error or raw results here...
});
It has the same required parameters as updateOne, a conditions query object and the update document object. In this example, the conditions query object is asking for any document that has an empty string in the impediments field, and we we'll be updating that to the string None, So you may be asking do you have to put the conditions query object and update document object in their own variables? No. This is just one code readability technique that you may want to consider. The bottom line is that these are just objects, and as shown here, can be placed as inline parameters and will work the same.
Model.deleteOne(...)
Parameters
conditons required
[callback] optional
const Standup = require('../models/project.js');
const qry = {isActive: false, name: 'Demo test'};
// deletes the FIRST document that matches query
Standup.deleteOne(qry, function(err){
// Handle any errors here
});
Just like we have methods to update one or many documents, we also have deleteOne and deleteMany. Let's select the deleteOne first. In this contrived example, we have two inactive project documents with the name field values of Demo test. We only want to delete one of those and keep the second in place for reuse later. We just don't need two of them. The conditions query object is set and passed into the standup model's deleteOne method and only the first matching document is deleted. Any errors will be passed back.
Model.deleteMany(...)
Parameters
conditons required
[callback] optional
const Standup = require('../models/project.js');
const qry = { isActive: false};
// deletes all documents that match query
Standup.deleteMany(qry, function(err){
// Handle any error here...
});
In this example where we examine the deleteMany method, we're illustrating a database cleanup operation where you may want to delete all inactive documents.
Model Methods
Let's multi-task
- findByIdAndUpdate
- findByIdAndDelete
There are a couple more update and remove methods that we'll briefly cover here before moving on to the demo, FindByIdAndUpdate and findByIdAndDelete.
Model.findByIdAndUpdate(...)
Parameters
id required
[update] optional
[options] optional
[callback] optional
const Standup = require('../models/standup.js');
const id = // Object, Number or String value passed in
const update = { project: 'Mongoose Demo' };
// delete one document, found by Id
Standup.findByIdAndUpdate(id, update, function(err, doc){
// Handle any error here
});
FindByIdAndUpdate does just what the name implies. As with the findById method we looked at earlier, the only condition we pass in is an id. And as with the modelUpdate method, we also pass in an optional update object here. The callback function, which is also optional is the same as the previous examples we have looked at.
The official Mongoose API documentation recommends that unless you have a good reason for using findByIdAndRemove that you should instead always use findByIdAndDelete. So that's what we'll look at next.
Model.findByIdAndDelete(...)
Parameters
id required
[options] optional
[callback] optional
const Standup = require('../models/standup.js');
const id = // Object, Number or String value passed in
// delete one document, found by Id
Standup.findByIdAndDelete(id, function(err, doc){
// Handle any error here...
});
FindByIdAndDelete, which is also completely understood by its name, finds a document by its unique id and then deletes it. Options and a callback function are both optional.
Demo: Querying Documents
Before we open up the code editor, it would be helpful to take another quick look at the partially completed demo application in order to review the API endpoints we may need to develop next.
As we saw before, when you're showing the 12 newest standup meeting notes here, it's an arbitrary number just so that we can illustrate limiting the number of documents returned. We also need to have the ability to supply a list of team members for this drop-down list. And if you recall, when adding a new note, we also have a list of active projects to select from, so we might as well go ahead and get that work done too.
Now that we've reviewed the demo application, we can see that we're going to need the following API GET routes in order to query the MongoDB documents we'll need.
Querying documents
- 12 newest standup notes
- Team member list
- Project list (active only)
We need a GET route to list out the 12 newest standup note documents entered, another route to get a list of team members for the filtered drop-down list, and while we're here, we'll go ahead and develop the route to get a list of active projects.
Let's open up Visual Studio Code now and get that work done. Make sure that MongoDB is running locally, and as we see, it is here on this tab, code . to open up Visual Studio Code, and the api folder under routes will open up standup.js to start with, and we'll finish off this GET route that was stubbed in earlier in the course.
The standup model has been required above, so we have access to the model's find method. We want the documents to come back to assorted by created date, so we can chain onto the query object returned by the find method asking the documents to be sorted by created On with a value of 1, meaning ascending order. We may actually want these documents descending, and if so, just change this to -1. Now we can execute the query object. And since this returns a promise, we can then into that, and using an arrow function to retrieve the returned documents, setting the response status to 200 OK, and returning the found and sorted documents as JSON. Now if something went wrong with this call, we can catch that error, and again, using an arrow function, set the status to 500 Server Error, and then pass back to the consumer of this API endpoint a JSON object with a friendly error message and the actual error that took place. Next, let's look at the team route. We first need to require the teamMember model. Now that we have access to that, as we just did with the standup note's GET endpoint, we will use the TeamMember model's find method, but this time, sort by the team member's name ascending, executing that query object, and returning the found TeamMember documents or handling any errors. What we need to do to get the list of active projects is nearly identical to this block of code, so let's copy this and modify as needed. We need to require the Project model here, so let's start with that, and then change the pasted in code a little here. Recall that we only want to list out the active projects, but currently, this will return all project documents. Let's build a query object to filter those down. Const qry =, and within this object, we only need the isActive field, and we want to be true, so we can use a comparison query operator, $eq for that. Now pass this qry object into the find method, and now we're only going to give back to active projects. Since we now have the ability to get a list of team members, we can return to the standup notes route file and build out another endpoint that allows us to get notes for a given team member's unique id. Router.get and with a path of standup/:teamMemberId. The colon here indicates a value that is being passed in as a parameter. The callback functions with properties of request and response are next as before. Now like we just saw with getting a list of active projects, let's build a query to get the standup notes by the teamMemberId, but before we do that, we need to make some adjustments to our schema and model file. Let's add a teamMemberId field to this collection with an object for the type, setting the type to a mongoose ObjectId and providing a reference to the teamMembers model file. MongoDB does not provide joins like a traditional relational database does, but we can reference other documents within our collection and store the ObjectId values to those in our document, which is exactly what we've done here with teamMemberId. Back in our standup API route now, we'll ask the query to find the _teamMemberId and cast the ID value provided in the request parameters as a mongoose ObjectId since that is its type as defined in the schema file. We'll need a reference to Mongoose to do this cast, however, so const mongoose = require mongoose. Now just like we did above, we'll utilize the standup model's find method. Sort by the createdOn date value, execute the query, and then pass the return documents and response back, or handle the error with a friendly message and error object passed back. Make sure that all these changes are saved and then open up our terminal window, change directories to the server folder, and now we can start the Express API server.
With that running now and no errors found, let's open up Postman to test this work out. Let's first test getting the 12 newest standup nodes at this URL, localhost port 8081/api/standup. That looks pretty good so far.
GET localhost:8081/api/standup
[
{
"_id": "5c1be99e740f102d5da6baab",
"teamMember": "Adarsh",
"project": "Softhinkers",
"workYesterday": "workYesterday goes here",
"workToday": "workToday goes here too",
"impediment": "none",
"createdOn": "2018-10-31T22:30:04.000Z",
"__v": 0
},
{
"_id": "5b9ec8e789bbd233f0b680c9",
"_teamMemberId": "5b9edd9064f634289ca895e4",
"teamMember": "David",
"project": "Trinity",
"workYesterday": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc est lectus, feugiat nec nulla et, auctor dignissim dolor. Nullam eget ex lectus. Nam in ipsum accumsan, pellentesque justo sed, placerat ante.",
"workToday": "Nulla nec dignissim mauris, sed dapibus dolor. Duis porttitor ullamcorper metus in vestibulum. ",
"impediment": "none",
"createdOn": "2018-09-16T21:19:35.534Z",
"__v": 0
},
{
"_id": "5b9ec8d789bbd233f0b680c8",
"_teamMemberId": "5b9edda464f634289ca895e8",
"teamMember": "John",
"project": "Morpheus",
"workYesterday": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc est lectus, feugiat nec nulla et, auctor dignissim dolor. Nullam eget ex lectus. Nam in ipsum accumsan, pellentesque justo sed, placerat ante.",
"workToday": "Nulla nec dignissim mauris, sed dapibus dolor. Duis porttitor ullamcorper metus in vestibulum. ",
"impediment": "none",
"createdOn": "2018-09-16T21:19:19.866Z",
"__v": 0
},
{
"_id": "5b9ec8d189bbd233f0b680c7",
"_teamMemberId": "5b9eddbb64f634289ca895e9",
"teamMember": "Summer",
"project": "Morpheus",
"workYesterday": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc est lectus, feugiat nec nulla et, auctor dignissim dolor. Nullam eget ex lectus. Nam in ipsum accumsan, pellentesque justo sed, placerat ante.",
"workToday": "Nulla nec dignissim mauris, sed dapibus dolor. Duis porttitor ullamcorper metus in vestibulum. ",
"impediment": "none",
"createdOn": "2018-09-16T21:19:13.751Z",
"__v": 0
},
{
"_id": "5b9ec8ac89bbd233f0b680c6",
"_teamMemberId": "5b9eddc764f634289ca895ea",
"teamMember": "Mary",
"project": "Matrix",
"workYesterday": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc est lectus, feugiat nec nulla et, auctor dignissim dolor. Nullam eget ex lectus. Nam in ipsum accumsan, pellentesque justo sed, placerat ante.",
"workToday": "Nulla nec dignissim mauris, sed dapibus dolor. Duis porttitor ullamcorper metus in vestibulum. ",
"impediment": "none",
"createdOn": "2018-09-16T21:18:36.756Z",
"__v": 0
},
{
"_id": "5b9ecdaf89bbd233f0b680cf",
"_teamMemberId": "5b9eddd764f634289ca895eb",
"teamMember": "Gayatri",
"project": "Nebuchadnezzar",
"workYesterday": "Donec viverra, nisi at aliquet sagittis, dui arcu efficitur nibh, eu posuere massa lectus eu diam.",
"workToday": " Vestibulum vel felis mauris. Maecenas erat nibh, mattis a tempus eu, tincidunt eleifend metus. Morbi cursus mauris in augue efficitur, sed venenatis nisi luctus.",
"impediment": "none",
"createdOn": "2018-09-15T23:01:03.111Z",
"__v": 0
},
{
"_id": "5b9ecdd3eb94542760bc0abb",
"_teamMemberId": "5b9eddd764f634289ca895eb",
"teamMember": "Gayatri",
"project": "Nebuchadnezzar",
"workYesterday": "Donec viverra, nisi at aliquet sagittis, dui arcu efficitur nibh, eu posuere massa lectus eu diam.",
"workToday": " Vestibulum vel felis mauris. Maecenas erat nibh, mattis a tempus eu, tincidunt eleifend metus. Morbi cursus mauris in augue efficitur, sed venenatis nisi luctus.",
"impediment": "none",
"createdOn": "2018-09-15T23:01:03.111Z",
"__v": 0
},
{
"_id": "5b9ecb1d64f634289ca895a4",
"_teamMemberId": "5b9edda464f634289ca895e8",
"teamMember": "John",
"project": "Morpheus",
"workYesterday": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc est lectus, feugiat nec nulla et, auctor dignissim dolor. Nullam eget ex lectus. Nam in ipsum accumsan, pellentesque justo sed, placerat ante.",
"workToday": "Nulla nec dignissim mauris, sed dapibus dolor. Duis porttitor ullamcorper metus in vestibulum. ",
"impediment": "none",
"createdOn": "2018-09-15T21:19:19.866Z",
"__v": 0
},
{
"_id": "5b9ecbd489bbd233f0b680ca",
"_teamMemberId": "5b9edd9064f634289ca895e4",
"teamMember": "David",
"project": "Trinity",
"workYesterday": "Sed mollis varius mauris id sodales. Proin lacinia porta malesuada. Aenean non diam quis nulla commodo viverra nec ut lorem.",
"workToday": "Fusce tincidunt lacus at purus fermentum, sed suscipit arcu convallis. Donec eu cursus nunc. Cras turpis orci, porttitor vel luctus non, aliquam at magna. Donec tincidunt mattis viverra.",
"impediment": "none",
"createdOn": "2018-09-14T21:19:35.534Z",
"__v": 0
},
{
"_id": "5b9ecc4c89bbd233f0b680cd",
"_teamMemberId": "5b9eddc764f634289ca895ea",
"teamMember": "Mary",
"project": "Matrix",
"workYesterday": "Sed mollis varius mauris id sodales. Proin lacinia porta malesuada. Aenean non diam quis nulla commodo viverra nec ut lorem.",
"workToday": "Fusce tincidunt lacus at purus fermentum, sed suscipit arcu convallis. Donec eu cursus nunc. Cras turpis orci, porttitor vel luctus non, aliquam at magna. Donec tincidunt mattis viverra.",
"impediment": "none",
"createdOn": "2018-09-14T21:19:35.333Z",
"__v": 0
},
{
"_id": "5b9ecc1689bbd233f0b680cc",
"_teamMemberId": "5b9eddbb64f634289ca895e9",
"teamMember": "Summer",
"project": "Morpheus",
"workYesterday": "Sed mollis varius mauris id sodales. Proin lacinia porta malesuada. Aenean non diam quis nulla commodo viverra nec ut lorem.",
"workToday": "Fusce tincidunt lacus at purus fermentum, sed suscipit arcu convallis. Donec eu cursus nunc. Cras turpis orci, porttitor vel luctus non, aliquam at magna. Donec tincidunt mattis viverra.",
"impediment": "none",
"createdOn": "2018-09-14T21:19:35.111Z",
"__v": 0
},
{
"_id": "5b9ecc0389bbd233f0b680cb",
"_teamMemberId": "5b9edda464f634289ca895e8",
"teamMember": "John",
"project": "Morpheus",
"workYesterday": "Sed mollis varius mauris id sodales. Proin lacinia porta malesuada. Aenean non diam quis nulla commodo viverra nec ut lorem.",
"workToday": "Fusce tincidunt lacus at purus fermentum, sed suscipit arcu convallis. Donec eu cursus nunc. Cras turpis orci, porttitor vel luctus non, aliquam at magna. Donec tincidunt mattis viverra.",
"impediment": "none",
"createdOn": "2018-09-14T21:19:35.000Z",
"__v": 0
},
{
"_id": "5b9ecd5689bbd233f0b680ce",
"_teamMemberId": "5b9eddd764f634289ca895eb",
"teamMember": "Gayatri",
"project": "Nebuchadnezzar",
"workYesterday": "Quisque varius diam eu purus congue, ac lobortis erat lobortis. Nulla facilisi. Sed porta, erat a rutrum condimentum, lorem est dignissim quam, nec sollicitudin lorem risus sed leo.",
"workToday": "Donec viverra, nisi at aliquet sagittis, dui arcu efficitur nibh, eu posuere massa lectus eu diam.",
"impediment": "none",
"createdOn": "2018-09-13T23:01:03.111Z",
"__v": 0
},
{
"_id": "5b99d45041fb05641c997e00",
"_teamMemberId": "5b9ecf9a64f634289ca895bb",
"teamMember": "Mark",
"project": "Trinity",
"workYesterday": "workYesterday goes here",
"workToday": "workToday goes here too",
"impediment": "none",
"createdOn": "2018-09-12T00:00:00.000Z",
"__v": 0
}
]
We have a nice list of standup notes here.
Now let's try getting notes for a particular team member. As shown in this example where the teamMemberId is passed in as an argument, but where is this value coming from?
GET localhost:8081/api/standup/5b9edd9064f634289ca895e4
Let's first test out the endpoint for getting a list of team members.
GET localhost:8081/api/team
[
{
"_id": "5b9edd9064f634289ca895e4",
"name": "David"
},
{
"_id": "5b9eddd764f634289ca895eb",
"name": "Gayatri"
},
{
"_id": "5b9edda464f634289ca895e8",
"name": "John"
},
{
"_id": "5b9ecf9a64f634289ca895bb",
"name": "Mark"
},
{
"_id": "5b9eddc764f634289ca895ea",
"name": "Mary"
},
{
"_id": "5b9eddbb64f634289ca895e9",
"name": "Summer"
}
]
And as you can see here, each document has a unique _id value. Send this GET request now, and things look good with this endpoint as well. We're only getting notes for this one team member as requested.
GET localhost:8081/api/standup/5b9edd9064f634289ca895e4
[
{
"_id": "5b9ec8e789bbd233f0b680c9",
"_teamMemberId": "5b9edd9064f634289ca895e4",
"teamMember": "David",
"project": "Trinity",
"workYesterday": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc est lectus, feugiat nec nulla et, auctor dignissim dolor. Nullam eget ex lectus. Nam in ipsum accumsan, pellentesque justo sed, placerat ante.",
"workToday": "Nulla nec dignissim mauris, sed dapibus dolor. Duis porttitor ullamcorper metus in vestibulum. ",
"impediment": "none",
"createdOn": "2018-09-16T21:19:35.534Z",
"__v": 0
},
{
"_id": "5b9ecbd489bbd233f0b680ca",
"_teamMemberId": "5b9edd9064f634289ca895e4",
"teamMember": "David",
"project": "Trinity",
"workYesterday": "Sed mollis varius mauris id sodales. Proin lacinia porta malesuada. Aenean non diam quis nulla commodo viverra nec ut lorem.",
"workToday": "Fusce tincidunt lacus at purus fermentum, sed suscipit arcu convallis. Donec eu cursus nunc. Cras turpis orci, porttitor vel luctus non, aliquam at magna. Donec tincidunt mattis viverra.",
"impediment": "none",
"createdOn": "2018-09-14T21:19:35.534Z",
"__v": 0
}
]
While we're at it, let's test out the Projects GET request, and that looks good too. We're only seeing documents where isActive is true. I think we're in pretty good shape now with the documents and data we need for our application through this Express API.