Every Firestore app eventually gets a search box, and then this question:
// What people try first
db.collection("products").where("name", "LIKE", "%shoe%") // doesn't exist
Cloud Firestore has no LIKE, no CONTAINS for strings, no full-text search and no case-insensitive matching. Its queries are built on indexes that support equality, ranges, in and array-contains, and that's all. Here are the options that do work, from simplest to most capable.
1. Prefix search with a range query
A string range can express "starts with":
const term = "sho";
db.collection("products")
.where("nameLower", ">=", term)
.where("nameLower", "<=", term + "")
.limit(20);
is a very high Unicode code point, so the range covers every string that starts with term.
- Comparisons are case-sensitive, so store a normalized copy (
nameLower, with accents stripped if needed) and query that. - It matches the start of the field only. "running shoe" won't match
shoe.
It's good enough for autocomplete on names, usernames or SKUs.
2. Keyword arrays with array-contains
Store searchable tokens on each document when you write it:
