If you want full text search capabilities in Firestore, you have limited options... until now. Firebase recommends Algolia. Yes, Google recommends Algolia instead of a Google product to have search capabilities in a Google product. I digress. Basically, you have these options:
UPDATE 10/23/22 - I have since retired this package. I recommend using my j-firebase package.
- Algolia - semi supports relational data
- Elastic Search - there are many forks as well, but ultimately you don't have all options out of the box
- MeiliSearch - host it yourself... see here
- Typesense - self-hosting as well
You can also use pretty much any search engine that you can connect your data to using firebase trigger functions. However, I like to keep my data in Firebase.
I have a hate/love relationship with Firestore like everyone else, but I wrote a package that allows you to full-text search data in Firestore, by creating indexes in Firestore. While I had three different ideas to do this, see here for my article, there is only one package I think works for most people...
Relevant Search
1.) npm i adv-firestore-functions
2.) Add the function to a onWrite trigger function like so:
import { soundex, relevantIndex } from 'adv-firestore-functions';
...
functions.firestore
.document('posts/{docId}')
.onWrite(async (change: any, context: any) => {
...
await relevantIndex(change, context, {
fields: ['content', 'summary'],
filterFunc: soundex
});
}
The soundex function allows you to do a fuzzy search. While not perfect, it should take care of most of your needs. I made it optional in case you don't want to use it, or you want to use your own changing algorithm.
3.) Add / Edit / Delete a new Post (or whatever collection) - Everything is changed and updated automatically on the backend.
4.) Make sure to add rules for your collection as well as _search and _events collection. They both need to be writable by Firestore, while _search needs to be readable on the client side by anyone.
5.) Use my pre-written Firestore Callable Function to read the indexed data on the front end:
import { relevantSearch } from 'adv-firestore-functions';
...
exports.searchPosts = functions.https.onCall((q, context) => {
return await relevantSearch({
query: q.query,
col: 'posts',
});
...
}
or write your own:
- Observable Version - This is my Trigram Search, but same premise
- Promise Version - Backend Version could easily be implemented on Front End
If you have other needs, check out my other searches:
- Which Full-Text Search Index Do I Use? - my Fireblog.io
- adv-firestore-functions - GitHub project
While I may or may not be done with Firestore, see Dear Firebase Team..., I wrote this package a while ago and needed to share it.
Post on GitHub if you have issues or ideas.
Thanks,
J
Top comments (2)
I've put this in my onWrite function. But is there a way to just run it against all items in an existing collection? I don't have have a "change" value to use for example if I were to implement it in a
functions.pubsub.schedule
functionNo, you need
change
to get the values. You could write your own. Check out the frontend version.dev.to/jdgamble555/quick-firestore...