demand_popularity_stats_repo.py 3.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. from __future__ import annotations
  2. from sqlalchemy import func, select
  3. from sqlalchemy.dialects.mysql import insert
  4. from supply_infra.db.models.demand_popularity_stats import DemandPopularityStats
  5. from supply_infra.db.repositories.base import BaseRepository
  6. _BATCH_SIZE = 500
  7. _UPSERT_COLUMNS = (
  8. "demand_word_name",
  9. "ext_pop_avg",
  10. "ext_pop_count",
  11. "plat_sust_pop_avg",
  12. "plat_sust_pop_count",
  13. "plat_ly_pop_avg",
  14. "plat_ly_pop_count",
  15. "recent_pop_avg",
  16. "recent_pop_count",
  17. "real_rov_7d_avg",
  18. "real_rov_7d_count",
  19. "real_vov_7d_avg",
  20. "real_vov_7d_count",
  21. )
  22. class DemandPopularityStatsRepository(BaseRepository[DemandPopularityStats]):
  23. """需求分类热度统计表 repository。"""
  24. model = DemandPopularityStats
  25. def get_latest_biz_dt(self) -> str | None:
  26. """返回热度统计表中最新业务日;无数据时返回 None。"""
  27. stmt = select(func.max(DemandPopularityStats.biz_dt))
  28. return self.session.scalar(stmt)
  29. def has_biz_dt(self, biz_dt: str) -> bool:
  30. """指定业务日是否存在热度统计数据。"""
  31. stmt = select(DemandPopularityStats.id).where(
  32. DemandPopularityStats.biz_dt == biz_dt
  33. ).limit(1)
  34. return self.session.scalars(stmt).first() is not None
  35. def list_by_biz_dt(self, biz_dt: str) -> list[DemandPopularityStats]:
  36. """返回指定业务日的全部热度统计行。"""
  37. stmt = select(DemandPopularityStats).where(DemandPopularityStats.biz_dt == biz_dt)
  38. return list(self.session.scalars(stmt).all())
  39. def search_by_word_name(
  40. self,
  41. keyword: str,
  42. biz_dt: str | None = None,
  43. ) -> list[DemandPopularityStats]:
  44. """按 demand_word_name 精确+模糊搜索;未指定 biz_dt 时不限日期,按 biz_dt 降序返回。"""
  45. keyword = (keyword or "").strip()
  46. if not keyword:
  47. return []
  48. stmt = select(DemandPopularityStats).where(
  49. DemandPopularityStats.demand_word_name.like(f"%{keyword}%")
  50. )
  51. if biz_dt:
  52. stmt = stmt.where(DemandPopularityStats.biz_dt == biz_dt)
  53. stmt = stmt.order_by(DemandPopularityStats.biz_dt.desc())
  54. return list(self.session.scalars(stmt).all())
  55. def list_by_biz_dt_and_belong_ids(
  56. self, biz_dt: str, belong_ids: list[int]
  57. ) -> list[DemandPopularityStats]:
  58. """按业务日 + demand_belong_category.id 列表查询热度行。"""
  59. if not belong_ids:
  60. return []
  61. rows: list[DemandPopularityStats] = []
  62. for i in range(0, len(belong_ids), _BATCH_SIZE):
  63. batch = belong_ids[i : i + _BATCH_SIZE]
  64. stmt = select(DemandPopularityStats).where(
  65. DemandPopularityStats.biz_dt == biz_dt,
  66. DemandPopularityStats.demand_category_id.in_(batch),
  67. )
  68. rows.extend(self.session.scalars(stmt).all())
  69. return rows
  70. def upsert_rows(self, rows: list[dict]) -> int:
  71. """按 (demand_category_id, biz_dt) 批量 upsert。"""
  72. if not rows:
  73. return 0
  74. affected = 0
  75. for i in range(0, len(rows), _BATCH_SIZE):
  76. batch = rows[i : i + _BATCH_SIZE]
  77. stmt = insert(DemandPopularityStats).values(batch)
  78. stmt = stmt.on_duplicate_key_update(
  79. **{col: stmt.inserted[col] for col in _UPSERT_COLUMNS}
  80. )
  81. result = self.session.execute(stmt)
  82. affected += result.rowcount or 0
  83. return affected