From ae8c20ea1ce04d3a21eb7020c0ba5bc15faf248f Mon Sep 17 00:00:00 2001 From: Cal Corum Date: Tue, 3 Mar 2026 17:03:19 -0600 Subject: [PATCH] fix: batch-fetch PitchingCardRatings instead of per-row queries (#19) Replace two get_or_none calls per row in sort_pitchers and sort_starters with a single batched SELECT for all card IDs, reducing N*2 queries to 1. Co-Authored-By: Claude Sonnet 4.6 --- app/routers_v2/teams.py | 39 ++++++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/app/routers_v2/teams.py b/app/routers_v2/teams.py index 35ee7d9..5a93553 100644 --- a/app/routers_v2/teams.py +++ b/app/routers_v2/teams.py @@ -279,7 +279,6 @@ def get_scouting_dfs(allowed_players, position: str): ) ) - def get_total_ops(df_data): ops_vl = df_data["obp_vl"] + df_data["slg_vl"] ops_vr = df_data["obp_vr"] + df_data["slg_vr"] @@ -587,15 +586,18 @@ def sort_pitchers(pitching_card_query) -> DataFrame | None: pitcher_df = pd.DataFrame(all_s).set_index("player", drop=False) logging.debug(f"pitcher_df: {pitcher_df}") + card_ids = pitcher_df["id"].tolist() + ratings_map = { + (r.pitchingcard_id, r.vs_hand): r + for r in PitchingCardRatings.select().where( + (PitchingCardRatings.pitchingcard_id << card_ids) + & (PitchingCardRatings.vs_hand << ["L", "R"]) + ) + } + def get_total_ops(df_data): - vlval = PitchingCardRatings.get_or_none( - PitchingCardRatings.pitchingcard_id == df_data["id"], - PitchingCardRatings.vs_hand == "L", - ) - vrval = PitchingCardRatings.get_or_none( - PitchingCardRatings.pitchingcard_id == df_data["id"], - PitchingCardRatings.vs_hand == "R", - ) + vlval = ratings_map.get((df_data["id"], "L")) + vrval = ratings_map.get((df_data["id"], "R")) ops_vl = vlval.obp + vlval.slg ops_vr = vrval.obp + vrval.slg @@ -664,15 +666,18 @@ async def get_team_sp( starter_df = pd.DataFrame(all_s).set_index("player", drop=False) logging.debug(f"starter_df: {starter_df}") + card_ids = starter_df["id"].tolist() + ratings_map = { + (r.pitchingcard_id, r.vs_hand): r + for r in PitchingCardRatings.select().where( + (PitchingCardRatings.pitchingcard_id << card_ids) + & (PitchingCardRatings.vs_hand << ["L", "R"]) + ) + } + def get_total_ops(df_data): - vlval = PitchingCardRatings.get_or_none( - PitchingCardRatings.pitchingcard_id == df_data["id"], - PitchingCardRatings.vs_hand == "L", - ) - vrval = PitchingCardRatings.get_or_none( - PitchingCardRatings.pitchingcard_id == df_data["id"], - PitchingCardRatings.vs_hand == "R", - ) + vlval = ratings_map.get((df_data["id"], "L")) + vrval = ratings_map.get((df_data["id"], "R")) ops_vl = vlval.obp + vlval.slg ops_vr = vrval.obp + vrval.slg