Angular full-text search in Firestore with Elastic App Search Firebase Extension
This tutorial provides a guide on how to use the Elastic App Search Extension, in order to quickly and efficiently search data saved in your Firestore Database. This extension works by syncing your configured Firestore data and automatically syncing it with the Elastics database.
≈ 14 minutes readIntroduction
This tutorial provides a guide on how to use the Elastic App Search Extension, in order to quickly and efficiently search data saved in your Firestore Database.
This extension works by syncing your configured Firestore data and automatically syncing it with the Elastics database.
Here we will build a search bar using Firebase, Angular, Elastic, and TailwindCSS
Getting started
Before starting the tutorial, we are required to have an API key to use the Elastic Search Firebase Extension.
If already signed
up, you can skip the next step:
Without an existing account, you can visit Elastic and select to start a free trial.
Next, continue with the signup process…
Provide a name for your deployment and select create deployment
Next, we will be required to set up a new search engine. Navigate to App Search -> Engines
Select to create a new engine.
Keep App search managed docs
selected and continue
.
Finally, add an engine called movies
and select create search engine
Once we have the search engine, navigate back to engines as we now need to add a meta engine.
Select to create a new meta engine
Add a name for the meta engine, and select the engine to be our previously created movies
engine.
Now, let’s install the Elastic Search Firebase Extension.
- Navigate to https://extensions.dev
- Search for Elastic and select
install
the extension.
After selecting which project to install the extension, we now have the option to configure the extension to our preferences:
Set your preferred location for the Installation.
Add movies
as the Collection path
Add movies
as the Elastic `App Search engine name`
We can access the API key by navigating to App Search
-> Credential
Copy the private key and add it to your configuration and select create secret
.
The Elastic Enterprise Search URL, will also find this as yours, on the Elastic credentials page – copy this and add it to your configuration.
Finally, let’s define the indexes that we want to search on. To keep this example, simply enter `name`.
Next, click install
.
Creating an app
For this example, we are going to develop in Angular (v15), using TailwindCSS as our styling framework.
To start with, we will require Angular CLI, so go ahead and globally install this dependency:
Next, let’s create a new project:
Feel free to choose Angular routing as an option, although it is not a requirement for this demo.
Choose `CSS` as your styling framework, we will be modifying this later anyway!
Next, let’s move into our new directory and run the app to make sure everything is working as expected:
Visiting the website running on the provided port and you will see the following:
Nice! Ok, now it’s time to add our styling framework, fortunately, Tailwind has a handy tutorial making this quick and easy to get started.
Adding Tailwind CSS
Following the instructions, we are required to run the following commands:
Next, update tailwind.config.js to the following:
Update `src/styles.css` with the following imports:
To ensure that we have fully installed Tailwind.
Navigate to src/app/app.component.html
and update the following line:
The resources tag should now be underlined to demonstrate we are using Tailwind.
- Restart the server if needed.
- Remember to clear the browser cache if results do not immediately show.
Ok, so we have an app running and our styling framework added. What’s next?
Creating the Movies component
Run the following command:
This will create a new folder called app/movies
and generate the following files:
- movies.component.css
- movies.component.html
- movies.component.spec.html
- movies.component.ts
This component will sit inside the main app component, let’s change the app.component.html
to only show a new header along with this new component:
So far so good!
Next, create a search box – this will allow us to filter on films when we have the correct data. Update `movies.component.html` to the following:
Now we have a search box – we should look next to find out data…
Setting up the data models.
Using the Elastic App Search API reference. We can define our models for receiving the data when we introduce our search functions. Based on this information, create a new file called `src/app/movie.ts` and add the following:
These models should match the expected response for our API.
Adding a service to the component
Now we have a model, we can add a service to retrieve the search results.
To do this, we are going to create an HTTP service to request data based on the Elastic Search API.
First, we need to add the ability client module to make an HTTP request and inject it into the main application.
Configuring the HTTP Client Module
Let’s add the dependency through NPM:
Add the following to `src/app/app.module.ts`:
And include as part of the modules imports:
Generating a Movie Service
Run the following command to create a new movie service file.
This will create two new files:
- movies.service.spec.ts
- movies.service.ts
Next, move these into the src/app/movies
folder.
And update the `movies.service.ts` file to:
Ensure that you replace the appropriate variables with your own credentials and URLs.
Navigate to credentials:
- private_key: Can be found as the private key, select to copy this key.
- Host Url: This is the endpoint URL located at the top of the page.
The search movies
function will receive a string (term), which will be used to pass the name query to the Elastic API.
Error Handling Service
Now we have created an HTTP service, we will require error handling. Although we are not expecting any errors and that is not part of this tutorial, this aspect at least provides good practices for when expanding beyond this demo.
Taking inspiration from the excellent StackBlitz, let’s look into adding error support for our service.
To add the HTTPErrorHandler, add a new file called src/app/http-error-handler.service.ts
and add the following:
Next, inject the HttpErrorHandler through the main application.
Finally, add the MovieService and HttpErrorHandler as providers in your `app.module.ts`
Connecting the Movie Service to our Movies component
In order to access this functionality from the UI, we will need to update the movies component to be the interface between the UI and the new service we have just created.
Setup forms for Search input
For entering data into our search, we will need to include the Angular Forms module to process our input. Install the dependency…
Then navigate back the `src/app/app.module.ts` file and included the import:
Then inject it into the main module:
Now we have a model, service, and a component to interface with – the movies HTML file can include an input for entering the search value:
Phew, that was a lot! We have now successfully added a service, component, and a view to allow our search component to pass a term to our service which sends an HTTP request to our Elastic Api.
Let’s see how this looks…
A simple test entering test will now start returning data from the search!
You should now see a successful request – our search is working and connected to the Elastic Search engine that we created at the start of the tutorial.
You’ll also notice, that there aren’t any actual search results! This is to be expected as we have not yet added any movies to our database. Let’s fix that…
Adding Movies with Firestore
The Elastic Search extension works by saving the specified collection data in its database when any records are written to Firestore. So let’s add that to our project:
Environment Configuration
Tip: When developing in the latest versions of Angular/AngularFire, limitations mean that cli cannot automatically create the environment files. This tutorial skips the bug, and encourages developers to create these files through environments cli.https://github.com/angular/angularfire/issues/3290
First, let’s create our environments for configuration.
Then include it as an import, ready for the angular installation.
Add AngularFire
Install AngularFire as a dependency
When prompted, select include `Firestore` as a selected feature.
Next, select your account and the Firebase project that you would like to use
Select a hosting site
And finally, select your application.
Once the installation has been completed, verify the `environments` folder and ensure your configuration has been correctly updated.
Now that AngularFire has been configured, we can add it to our main application
Then inject it as an import
Now we have added Firebase to our application, we can look to see how to how transport this information from the UI to the search component, to this we utilize Angular forms.
Creating a form
Angular has a library for creating forms called `ReactiveFormsModule`, let’s add that in our imports from the main app:
Then include in the imports
Now we have the new forms injected as a dependency into the application.
The next step is to navigate back to the `src/app/movies/movies.component.ts` module and add the following function for adding a movie:
Adding Reactive Forms to the Movie component
First, we need to add our imports
Next, create a new form above the constructor:
Then include a reference inside the constructor below:
Create a new form for initialisation
Now we have a form available, we can create our new function for submitting the new movie information too…
Finally, let’s add a text box and submit button to HTML to add a new movie:
Submitting a new movie should now print out the name of the movie in the console…
Ok, great. We’re nearly there! Let’s add Firestore to our add movie function…
Updating Firestore through the Movie function
Import the required Firestore dependencies:
This allows a firestore reference and a firestore collection reference.
Next, add a private reference above the constructor:
Inject Firestore into the constructor and reference the result to the moviesCollection
.
Note: Ensure that the collection name matches the name provided in the Extension configuration form the start of the tutorial
Finally, add the document to a collection when the movie is submitted…
Updating Typescript Configuration
As is often the case with imported modules and Typescript, we will occasionally see errors like the following:
To fix this we are going to add some additional configuration to the `tsconfig.json` file at the root of our project.
Add the following to the compilerOptions
object:
Restart the server if this does not automatically compile.
Now let’s test adding a movie:
Following submission, your Firestore database should have a new record!
Woo! ok we’re nearly, there…
Displaying the results
So we have one last thing to do…and that is to show the results of the search from the Elastic API.
Add the following HTML to src/app/movies/movies.component.html
Allowing strict type initialization
Now before we search, one last bit of configuration. You should now see the following error in your app and on the website…
To fix this, go back to your tsconfig.json
file and update the following property:
This update will ensure that the typescript compiler ignores any properties that may or not exist. The `?` optional operator will allow this to be safely typed at runtime.
Testing our search component
We made it! Let’s try our search function:
To make sure all updates are working Let’s add another movie…
And let’s test for the new movies we have just added.
And that is everything, we have now introduced Search on our Firebase application!
Here is the full search in action…
Summary
In this tutorial, we have learned how to create an Angular app that allows for the searching of a Firebase collection by using the Elastic App Search API. This is a basic search example and with more fields and indexing, a Firestore Search feature would be a very powerful tool!
Feel free to clone the project from the Invertase samples directory and share your ideas with us. We’d love to see what developers can create using the power of Firebase Extensions!
Stay tuned for more updates and exciting news that we will share in the future. Follow us on Invertase Twitter, Linkedin, and Youtube, and subscribe to our monthly newsletter to stay up-to-date. You may also join our Discord to have an instant conversation with us.