Semantic Event Search
Problem
Section titled “Problem”ParentConnect’s event search was keyword-based — users had to guess the right words to find what they were looking for. Searching “something fun for kids this weekend” returned nothing, because no event had those exact words in its title. Parents think in intent (“outdoor activities near me”), not in event titles (“Spring Fling at Sunset Park”).
The app needed a search that understands meaning, respects geography, and works without requiring the user to know what exists.
Approach
Section titled “Approach”
A Firebase callable Cloud Function takes a natural language query, the user’s location, a search radius in miles, and optional date filters.
Query → Embedding
The user’s query is sent to Vertex AI’s text-embedding-004 model with SEMANTIC_SIMILARITY as the task type, producing a 768-dimension vector — the same model and task type used to embed the events themselves (see Event Embedding Pipeline).
Geographic filtering
The search radius (in miles) is converted to meters and passed to geohashQueryBounds from the geofire-common library. This generates geohash range queries that efficiently pull only events within the geographic bounding box from Firestore — no full-collection scan needed. Each candidate is then checked with an exact distance calculation (Haversine) and filtered to the requested radius.
Similarity scoring
Every event within the radius has its stored embedding compared to the query embedding via cosine similarity. Events below the similarity threshold are dropped. The threshold defaults to 0.7 but is read from a Firestore config document (app_config/main) on every request — tuneable in production without redeployment.
Sorting
Results are sorted by similarity score (highest first). When two events have nearly identical similarity (within 0.01), the closer event wins.
Date filtering
Optional startDate and endDate parameters narrow results to a time window. Events outside the range are excluded before scoring.
Usage tracking
Each search increments a daily counter in a user_ai_usage collection, keyed by user ID. The counter resets at UTC midnight. Tracking runs async and never blocks or fails the search.
Results
Section titled “Results”- Users search with natural language — “art classes for toddlers”, “free outdoor activities this weekend”, “birthday party venues” — and get semantically relevant results ranked by match quality and distance
- Geohash-based pre-filtering keeps Firestore reads efficient even as the event catalog grows
- The similarity threshold is tunable from the Firestore admin config — no code change, no deploy
- Query length is capped (configurable, default 100 characters) to control Vertex AI costs
- AppCheck enforcement protects the endpoint from abuse