You have unlimited access as a PRO member
You are receiving a free preview of 3 lessons
Your free preview as expired - please upgrade to PRO
Contents
Recent Posts
- Object Oriented Programming With TypeScript
- Angular Elements Advanced Techniques
- TypeScript - the Basics
- The Real State of JavaScript 2018
- Cloud Scheduler for Firebase Functions
- Testing Firestore Security Rules With the Emulator
- How to Use Git and Github
- Infinite Virtual Scroll With the Angular CDK
- Build a Group Chat With Firestore
- Async Await Pro Tips
Multi-Property Data Filtering With Firebase and Angular 4
Episode 32 written by Jeff DelaneyMulti-property data filtering an array data is a common need in web applications. In this lesson, I outline the best options for filtering your data when you want to achieve something similar to using multiple WHERE
conditions in a SQL database query.
Let’s be perfectly clear… Firebase is somewhat limited when you need to filter your data on multiple conditions server-side.
The Realtime Database can only filter one property value at a time!
Consider the following example.
db.list('/animals', { |
That’s the best we can do (out of the box) when filtering by values on the server. But don’t worry yet, I’m going to share four potential solutions.
Option 1 - Client Side Filtering
You can only filter by one value at a time in Firebase, but you can add additional client-side filtering all other parameters as long as you can fit the data into memory.
Pros
- Best performance
- Unlimited flexibility
Cons
- May not be possible with large datasets
Example of Advanced Client-Side Data Filtering
In this example, I subscribe to a FirebaseListObservable
of animals, which emits an array of objects, then use lodash to remove objects based on data filtering rules. We can filter javascript objects with multiple rules by combining filter()
and conforms()
. Conforms takes an object of functions (our filters) that evaluate to true or false. This allows us to create reusable functions that solve common filtering problems, such as exact string matching, less-than, greater-than, or any other logic you so desire.
Our data looks like this:
And this is how to filter it client-side:
import { Component, OnInit } from '@angular/core'; |
In the HTML, we can bind the user inputs using ngModel
, then update the filtering rules anytime a value changes. The filtering will be instantaneous because the code is running client side. We still have a realtime connection to Firebase so any new entires will stay in sync.
<h2>Filters</h2> |
Option 2 - Composite Keys
Another potential option for data filtering is to use composite keys. A composite key just combines the the keys and values between multiple parameters.
data = { |
As you might imagine, trying to implement this strategy for multiple params will lead to a ridiculous amount of composite keys. It follows the pattern Eularian Numbers, shown in the table below:
If we wanted to filter by 9 different parameters, we would need to maintain 502 composite key combinations on every object. Yikes!
Also, check out QueryBase - a library from the Firebase team that attempts to create composite keys automatically. It is not production ready, but may give you some ideas on how to implement this concept into your app.
Pros
- Server-side filtering for up to 3 properties.
Cons
- Additional data maintenance.
- Only practical for 3 filter-able properties or fewer.
- Increases risk of data anomalies.
Example of Composite Keys
In this example, we add 4 composite keys to an object to handle the filtering of 3 different properties. You would want to build this data programmatically in a real app, but this example demonstrates how the end result should look.
createData() { |
Option 3 - Filter by Tags
Another option that can work in some cases is to filter data based on tags. In this case, you demoralize the data to be queried based on tags associated with it.
You query the keys from the selected tags, then compute the intersection of the keys. The database might look like this:
Pros
- Server-side filtering for unlimited properties
Cons
- Additional data maintenance and duplication
- Only works for exact matches (no numeric ranges)
- Increases risk of data anomalies.
- Requires multiple queries
tags |
Next, you query each tag and find intersection of keys between the the emitted values using the lodash intersection helper, for example _.intersection([tagFoo, tagBar, tagBaz])
.
Option 4 - Use a 3rd Party Indexing Solution
Running complex multi-property filtered queries is an inherently challenging problem with any NoSQL database. If this type of feature is integral to your app, you might consider using a third-party data indexing service that specializes in this task. Algolia, ElasticSeach, and Apache Solr are the most well-known solution providers.
I recently posed a two-part lesson about using Algolia with Angular4 and Firebase. It’s free (up to a volume limit) and can be easily synced with your database via Firebase Cloud Functions.
That’s it for advanced data filtering with Firebase. Let me know if you have questions in the comments.