Sorting and Filtering Data with Firebase Realtime Database
Tags: webdev, codenewbie, database, javascript
Published: 2020-11-09 03:12:19

We are continuing on with the bug tracking app we've been building!  Today, we will go through sorting and filtering data with Firebase, but I will also share with you a simple workaround to sort the data. 

*A couple of notes:*

*I did make a few changes since my last post, where I replaced the `assignedTo` attribute of an issue with `date`, as this bug tracker is supposed to be for personal use, not with a whole team, and I'd also like to know when the date was first created in order to keep track of things better.*

*Additionally, I decided to discontinue the use of [`chance.guid()`](https://chancejs.com/) to generate a string of random numbers and letters to assign as the `id` number of an issue.  I instead created a function using the date and time of an issue to formulate its `id` number:*

```javascript
function generateId() {
  const newDate = new Date();

  const date = newDate.toLocaleDateString("en-US", {
    year: "numeric",
    month: "2-digit",
    day: "2-digit",
  }).replace(/[^0-9]/g, "");
    
  const time = newDate.getTime().toString();

  return date + time;
}
```

## Sorting Data with Firebase Realtime Database

For this bug tracking app, ideally we would probably want the issue tickets to be in chronological order, with oldest at the top and newest at the bottom. 

Firebase has the following methods that can be used to determine what order results are rendered in (straight from the documentation):

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/ffuhpm3wbzs47y8m6n5v.jpg) 

In our case, we can use `orderByChild()` and pass in `"date"` so that the issues will render in date order:

```javascript
function readIssues() {
  issuesRef.orderByChild("date").on("value", function(snapshot) {
    snapshot.forEach(snap => {
      const issue = snap.val();
  // More code but we don't need to see it here
}
```

*Please keep in mind that we can only use one order-by method at a time, or else we will get an error.*

## Filtering Data

Firebase Realtime Database offers the following methods that can be constructed with an order-by method:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/rdxdp9nr7ksmeondagru.jpg)

For our purposes, we will focus on the `equalTo()` method. 

In our bug tracker, we assign a priority level for each new issue:  `"Low"`, `"Medium"` or `"High"`.  Let's say we want to filter the issues to render those of one priority level, such as if we want to only focus on the most pressing, high-priority tasks at hand.

To get started, we can create buttons to click for each priority level, so in our `index.html` file it would look something like this: 

```html
<div>
  <button id="all" class="btn btn-primary">All</button>
  <button id="low" class="btn btn-info">Low</button>
  <button id="medium" class="btn btn-warning">Medium</button>
  <button id="high" class="btn btn-danger">High</button>
</div>
```

Now going into the `main.js` file, we can create an event listener on the button that is being clicked to trigger a function that will utilize the `equalTo()` method and pass in the priority level.  If we were going to filter for only high priority issues, the code could look something like this: 

```javascript
document.getElementById('high').addEventListener('click', e => {
  document.getElementById('issuesList').innerHTML = "";
  readFilteredIssues(e);
})

function readFilteredIssues(e) { 
 
 issuesRef.orderByChild('priority').equalTo(e.target.innerHTML).on("value", function(snapshot) {
  snapshot.forEach(snap => {
    const issue = snap.val();

  // The rest of the code is the construction of the HTML elements we want rendered on the DOM
)}
```

<img width="50%" style="width:50%" src="https://media.giphy.com/media/OMM8SXlQbw7QuOxeZP/giphy.gif">

## Helpful Links

[How query data is ordered](https://firebase.google.com/docs/database/web/lists-of-data#data-order)

[Sorting and filtering data](https://firebase.google.com/docs/database/web/lists-of-data#sorting_and_filtering_data)