From cccc6cb5c54a66f1d7771674600b102b2af74914 Mon Sep 17 00:00:00 2001 From: RohanExploit <178623867+RohanExploit@users.noreply.github.com> Date: Tue, 19 May 2026 14:17:45 +0000 Subject: [PATCH] =?UTF-8?q?=E2=9A=A1=20Bolt:=20Consolidate=20aggregate=20q?= =?UTF-8?q?ueries=20in=20field=20officer=20stats?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .jules/bolt.md | 4 +++ backend/routers/field_officer.py | 52 +++++++++----------------------- 2 files changed, 19 insertions(+), 37 deletions(-) diff --git a/.jules/bolt.md b/.jules/bolt.md index dd183ea2..3a3097fb 100644 --- a/.jules/bolt.md +++ b/.jules/bolt.md @@ -93,3 +93,7 @@ ## 2026-05-20 - Joined Queries for Integrity Verification **Learning:** Performing multiple sequential database queries to verify cryptographically chained records (e.g., fetching a record and then its associated token/metadata from another table) introduces unnecessary latency and increases database load. **Action:** Consolidate associated data retrieval into a single SQL `JOIN` query within the verification hot-path. This reduces database round-trips and improves end-to-end latency for blockchain-style integrity checks. + +## 2026-05-19 - Single Aggregate Query for Multi-Metric Counts +**Learning:** Consolidating multiple database aggregate queries into a single query using SQLAlchemy `func.sum(case(...))` for categorical counts alongside other aggregates (like `avg` and `count(distinct)`) measurably improves performance by reducing database round-trips and redundant table scans. +**Action:** Use a single `db.query()` with `func.sum(case(...))` when aggregating across multiple distinct categorical columns and regular metrics simultaneously. Remember to explicitly cast to int/float with `or 0` fallback, as `func.sum` can return `None`. diff --git a/backend/routers/field_officer.py b/backend/routers/field_officer.py index 3801ccce..2ede668f 100644 --- a/backend/routers/field_officer.py +++ b/backend/routers/field_officer.py @@ -437,52 +437,30 @@ def get_visit_statistics(db: Session = Depends(get_db)): if cached_json: return Response(content=cached_json, media_type="application/json") - # Optimized: Use a single aggregate query to fetch multiple statistics in one database roundtrip - agg_stats = db.query( + # Optimized: Consolidating multiple database aggregate queries into a single query using func.sum(case(...)) + res = db.query( + func.count(FieldOfficerVisit.id).label('total_visits'), func.count(func.distinct(FieldOfficerVisit.officer_email)).label('unique_officers'), - func.avg(FieldOfficerVisit.distance_from_site).label('avg_distance') + func.avg(FieldOfficerVisit.distance_from_site).label('avg_distance'), + func.sum(case((FieldOfficerVisit.verified_at.isnot(None), 1), else_=0)).label('verified_visits'), + func.sum(case((FieldOfficerVisit.within_geofence == True, 1), else_=0)).label('within_geofence'), + func.sum(case((FieldOfficerVisit.within_geofence == False, 1), else_=0)).label('outside_geofence') ).first() - counts = db.query( - FieldOfficerVisit.verified_at.isnot(None).label("is_verified"), - FieldOfficerVisit.within_geofence, - func.count(FieldOfficerVisit.id) - ).group_by( - FieldOfficerVisit.verified_at.isnot(None), - FieldOfficerVisit.within_geofence - ).all() - - total_visits = 0 - verified_visits = 0 - within_geofence_count = 0 - outside_geofence_count = 0 - - for is_verified, within_geofence, count in counts: - c = count or 0 - total_visits += c - if is_verified: - verified_visits += c - if within_geofence is True: - within_geofence_count += c - elif within_geofence is False: - outside_geofence_count += c - - unique_officers = agg_stats.unique_officers or 0 - average_distance = agg_stats.avg_distance - - # Round to 2 decimals if not None - if average_distance is not None: - average_distance = round(float(average_distance), 2) - else: - average_distance = 0.0 - + total_visits = int(res.total_visits or 0) if res else 0 + unique_officers = int(res.unique_officers or 0) if res else 0 + average_distance = float(res.avg_distance or 0.0) if res else 0.0 + verified_visits = int(res.verified_visits or 0) if res else 0 + within_geofence_count = int(res.within_geofence or 0) if res else 0 + outside_geofence_count = int(res.outside_geofence or 0) if res else 0 + result_data = { "total_visits": total_visits, "verified_visits": verified_visits, "within_geofence_count": within_geofence_count, "outside_geofence_count": outside_geofence_count, "unique_officers": unique_officers, - "average_distance_from_site": average_distance + "average_distance_from_site": round(average_distance, 2) } # Cache serialized JSON