Personal Catalogue: React & Firebase — Chapter 6, Exercise 2 ===================================================================== TASK Build searchByTitlePrefix() and run it twice against a real book titled "Clean Code" — once with the query "Clean" and once with "Code" — recording both real results and explaining precisely why one succeeds and the other returns nothing. SOLUTION import { collection, query, where, orderBy, getDocs } from "firebase/firestore"; async function searchByTitlePrefix(prefix) { const q = query( collection(db, "items"), orderBy("title"), where("title", ">=", prefix), where("title", "<=", prefix + "") ); const snapshot = await getDocs(q); return snapshot.docs.map((d) => ({ id: d.id, ...d.data() })); } Run 1: const results = await searchByTitlePrefix("Clean"); console.log(results); Output: [{ id: '...', title: 'Clean Code', ... }] Run 2: const results = await searchByTitlePrefix("Code"); console.log(results); Output: [] Explanation: The query only matches documents whose title field falls between the given prefix and that same prefix followed by a very high Unicode character — which, given how Firestore orders strings, means "starts with this exact prefix." "Clean Code" genuinely starts with "Clean", so it falls inside that range and the first query matches it. "Clean Code" does NOT start with "Code" — "Code" is the second word, not the beginning of the string — so the title "Clean Code" sorts before the range ["Code", "Code"] entirely and never falls inside it. The query isn't broken; it's doing exactly what a prefix-bounded range query is defined to do. It simply isn't the same operation as "does this string contain this substring anywhere," which is the real question this app actually needs answered and the reason searchItems() (using plain string .includes()) is what the rest of this chapter actually builds on. WHY THIS WORKS AS AN ANSWER ---------------------------- It runs both real queries against the same document and records the genuinely different real outcomes, then explains the mechanism (a range bound on the string's own start) precisely enough to make clear why "Code" failing isn't a bug — it's the query correctly enforcing a constraint that has nothing to do with substring position.