Files
Oxicloud/migrations/20260801000003_places_geo_index.sql
T
Claude f4b431bb03 feat(places): backend for the photo map (geo clusters API)
Phase 1 server side, gated on OXICLOUD_ENABLE_PLACES (off by default):

- migration: partial index on storage.file_metadata(longitude, latitude).
- FileBlobReadRepository::list_geo_clusters — plain-SQL grid aggregation
  (no PostGIS) scoped to the caller's own non-trashed photos, returning a
  centroid, count and a representative file id per non-empty cell.
- PlacesService (caller_id-scoped; user-scoped data needs no authz check,
  mirroring RecentService) with a zoom→cell-size mapping.
- GET /api/photos/geo?bbox=w,s,e,n&zoom=N returning GeoCluster[]. The route
  is mounted only when the Places service is present, and is registered in
  the OpenAPI path list.

The map frontend (PMTiles serving + MapLibre module) is deferred pending
the basemap-sourcing and vendoring decision.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JW6ghFMDtnRYuYNzZhb47M
2026-06-19 10:57:01 +00:00

11 lines
876 B
SQL

-- ════════════════════════════════════════════════════════════════════════
-- Places (photo map): partial index for fast bounding-box scans over the
-- caller's geotagged photos. Plain B-tree on (longitude, latitude); no
-- PostGIS required. The partial predicate keeps the index small — only rows
-- that actually carry GPS coordinates are indexed.
-- ════════════════════════════════════════════════════════════════════════
CREATE INDEX IF NOT EXISTS idx_file_metadata_geo
ON storage.file_metadata (longitude, latitude)
WHERE latitude IS NOT NULL AND longitude IS NOT NULL;