"""Fallback name/address search over our own `places` dataset. Used when the user denies location permission and types a place of interest, or when 2GIS's own geocoding API isn't wired into a given client flow yet. """ import logging from geoalchemy2 import Geometry from sqlalchemy import and_, cast, func, select from sqlalchemy.orm import Session from app.models.city import City from app.models.enums import ContentLanguage, ContentLength from app.models.place import Place from app.models.place_content import PlaceContent logger = logging.getLogger("guidecity.geocoding") def search_places( db: Session, *, q: str, language: ContentLanguage, city_slug: str | None = None, limit: int = 20, ): stmt = ( select( Place, PlaceContent, func.ST_X(cast(Place.location, Geometry)).label("lon"), func.ST_Y(cast(Place.location, Geometry)).label("lat"), ) .join( PlaceContent, and_( PlaceContent.place_id == Place.id, PlaceContent.language == language, PlaceContent.length == ContentLength.short, ), ) .where(Place.is_active.is_(True)) .where(PlaceContent.title.ilike(f"%{q}%")) .limit(limit) ) if city_slug is not None: stmt = stmt.join(City, City.id == Place.city_id).where(City.slug == city_slug) results = db.execute(stmt).all() logger.info("name search q=%r city_slug=%s lang=%s -> %d result(s)", q, city_slug, language, len(results)) return results