This deliverable demonstrates using MongoDB to persistently store user's scores and authentication data.
You can view this application running here: Example Simon DB
This version of Simon calls the database service to save high scores and authorization data. This creates a third layer in our Simon technology stack.
- Frontend client application - HTML/CSS/JavaScript/React
- Backend web service - Caddy, Node.js, Express
- Database service - MongoDB
You need to get a MongoDB Atlas account and create a database cluster that you can use as your database service. If you have not done that yet, go back and review the instruction on data services.
Make sure you follow the instruction given previously about providing and protecting your MongoDB credentials in a file named dbConfig.json. This file will get deployed to production with the deployService.sh script.
{
"hostname": "cs260.abcdefg.mongodb.net",
"userName": "myMongoUserName",
"password": "toomanysecrets"
}Note
Make sure you include dbConfig.json in your .gitignore file so that it does not get pushed up to GitHub.
Now you can make a connection to your MongoDB server hosted with Atlas. You also want to test your connection to make sure it is available before you start handling user requests.
const url = `mongodb+srv://${config.userName}:${config.password}@${config.hostname}`;
const client = new MongoClient(url);
const db = client.db('simon');
(async function testConnection() {
try {
await db.command({ ping: 1 });
} catch (ex) {
console.log(`Unable to connect to database with ${url} because ${ex.message}`);
process.exit(1);
}
})();Because MongoDB was designed to represent its data in a way that is very similar to JavaScript objects, it is very easy for us to insert, update, and search for our data objects.
The following shows the majority of the database calls to MongoDB.
function getUser(email) {
return userCollection.findOne({ email: email });
}
function getUserByToken(token) {
return userCollection.findOne({ token: token });
}
async function addUser(user) {
await userCollection.insertOne(user);
}
async function updateUser(user) {
await userCollection.updateOne({ email: user.email }, { $set: user });
}
async function addScore(score) {
return scoreCollection.insertOne(score);
}
function getHighScores() {
const query = { score: { $gt: 0, $lt: 900 } };
const options = {
sort: { score: -1 },
limit: 10,
};
const cursor = scoreCollection.find(query, options);
return cursor.toArray();
}You can see that in most cases it is a simple passthrough from the application logic found in index.js to MongoDB. The exception is the getHighScores call where we need to provide the parameters for searching the scores and limiting the results to the top 10 highest scores.
Get familiar with what this code teaches.
- Clone the repository to your development environment.
git clone https://github.com/webprogramming260/simon-db.git
- Set up your Atlas credentials in a file named
dbConfig.jsonthat is in the same directory asdatabase.js. - Add
dbConfig.jsonto your.gitignorefile so that it doesn't put your credentials into GitHub accidentally. - Review the code and get comfortable with everything it represents.
- Debug the code in your browser by hosting it from a VS Code debug session. This video on debugging a node.js based service will step you through the process.
- See how data is populated in the database by viewing the contents of the database using the MongoDB Atlas console.
- Make modifications to the code as desired. Experiment and see what happens.
-
Deploy to your production environment using the
deployService.shscript found in the example class application. Take some time to understand how it works../deployService.sh -k <yourpemkey> -h <yourdomain> -s simon
For example,
./deployService.sh -k ~/keys/production.pem -h yourdomain.click -s simon -
Update your
startuprepository notes.md with what you learned. -
Make sure your project is visible from your production environment (e.g. https://simon.yourdomain.click).


