Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
1 - Databases, Part 2
In this chapter, we're going to finish the remaining features of the original Leaderboard application. Then we'll start working on some new features.
This button should be outside of the "each" block and have a class attribute of "increment".
To then make this button do something, create a "click" event that's attached to the "increment" class. This event will now trigger when the "Give
5 Points" button is clicked.
Within the event, we need to grab the unique ID of the selected player.
We can then use that ID to find a player inside the "PlayersList" collection and increment the value of that player's "score" field by 5.
To access the unique ID of the selected player, use the "Session.get" function to retrieve the value of the "selectedPlayer" session, and store the
result in a "selectedPlayer" variable.
Because of this code, users can select any of the players in the list,
click the "Give 5 Points" button, and then see that player's ID in the Console.
Mongo Operators
Inside the "click increment" event, remove the console.log statement and
replace it with a "PlayersList.update" function.
There are two pieces of data we need to pass into the update function.
Second, we need to pass through some data in the JSON format, and whatever
data we pass through here is how the document for the selected player will
be modified.
Based on this change, this statement will find the document of the currently selected player and change that selected player's "score" field to "5".
If you select a player and click the "Give 5 Points" button, the name of
that player will disappear. The value of the "score" field will change to
"5", just as planned, but the "name" field will be completely removed from
the document.
You can see proof of this by using the find and fetch function.
This might seem like a bug but, by default, the update function works by
deleting the original document and creating a new document with the data
that we specify.
The value of the _id" field will remain the same, but because we've only
specified the "score" field inside the update function, that's the only
other field that will continue to exist after the document is modified.
To account for this, we need to use a Mongo feature that allows us to set
the value of the "score" field without deleting the original document.
Inside the update function, pass through a "set" operator as the second argument, making sure to precede this operator with a dollar-sign. This operator allows us to modify fields in a document without deleting the original
document.
After the colon, we just have to pass through the fields we want to modify,
along with their values.
If we select a player and click the "Give 5 Points" button, the value of
the "score" field of that player's document will change without affecting
the rest of the document.
At the moment, we're only setting the value of the "score" field, rather
than incrementing it. So no matter how many times we click the button, the
value of the "score" field will never go any higher than "5".
To fix this problem, replace the "set" operator with an "inc" operator.
By using this special Mongo operator, whenever the update function is triggered, the value of the selected player's "score" field will now be incremented by a value of "5".
What's also neat is how easily we can allow users to decrement the scores
of players using very similar code.
Then, inside the JavaScript file, create a copy of the "click increment"
event, making sure to separate the events with commas.
And second, pass a value of minus 5 into the "inc" operator, rather than a
value of "5". This reverses the effect of the operator, meaning the "Take 5
Points" button will now decrement the selected player's score.
Sorting Documents
By default, the players in our list are ranked by the time they were added
to the "PlayersList" collection, rather than being ranked by their scores.
To begin, pass through a pair of curly braces into the find function.
By using these curly braces, we're explicitly stating that we want to retrieve all of the data from the "PlayersList" collection. This is the default behavior of the find function, but by passing through the curly
braces as the first argument, we can pass through a second argument, and
that's what we need to do.
As the second argument for the find function, pass through another pair of
curly braces, along with a "sort" method.
This method allows us to define how we want to sort the retrieved documents.
Pass through the name of whatever fields you want to sort by, which in this
case is the "score" field, and also pass through a value of "-1".
If these players have the same score, Bill should be ranked above Bob because, alphabetically, his name comes first.
But at the moment, this won't happen because Bob was added to the collection before Bill.
To fix this, pass the "name" field into the "sort" method, but this time,
pass through a value of "1" instead of "-1".
The players will still be primarily sorted by their scores, but if any
players have the same scores, those players will be additionally sorted by
their names.
Individual Documents
When a user selects one of the players in the list, that player's name
should appear beneath the list.
To achieve this, create a "selectedPlayer" helper function for the "leaderboard" template.
Within this function, retrieve the ID of the currently selected player using the "Session.get" function and store this inside a "selectedPlayer"
variable.
Then create a return statement that uses a findOne function to retrieve the
selected player's document.
We haven't talked about the "findOne" function before, but this function
has a couple of advantages over the regular find function:
And second, there's a performance benefit, because while the find function
will search through the collection for all possible matches to a query, the
findOne function will stop searching as soon as a match is found.
As such, if you ever need to only retrieve a single document, it's best to
use the findOne function.
But if we save the file, the output won't look quite right, and that's because the "findOne" function is retrieving the player's entire document.
To fix this, we need to specify that we only want to retrieve the value of
the document's "name" field. This can be achieved with dot notation.
We can also use this same conditional to make sure the interface buttons
don't appear unless a player is currently selected.