| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157 |
- from __future__ import annotations
- from sqlalchemy import func, select
- from sqlalchemy.dialects.mysql import insert
- from supply_infra.db.models.demand_video_expansion import (
- DemandVideoExpansion,
- DemandVideoExpansionRun,
- )
- from supply_infra.db.repositories.base import BaseRepository
- _BATCH_SIZE = 500
- class DemandVideoExpansionRepository(BaseRepository[DemandVideoExpansion]):
- """需求视频点位拓展结果 repository。"""
- model = DemandVideoExpansion
- def get_active_by_id(self, expansion_id: int) -> DemandVideoExpansion | None:
- stmt = select(DemandVideoExpansion).where(
- DemandVideoExpansion.id == int(expansion_id),
- DemandVideoExpansion.is_delete == 0,
- )
- return self.session.scalars(stmt).first()
- def has_video(
- self,
- *,
- biz_dt: str,
- source_demand_grade_id: int,
- video_id: str,
- ) -> bool:
- stmt = select(DemandVideoExpansion.id).where(
- DemandVideoExpansion.biz_dt == biz_dt,
- DemandVideoExpansion.source_demand_grade_id == int(source_demand_grade_id),
- DemandVideoExpansion.video_id == video_id,
- DemandVideoExpansion.is_delete == 0,
- )
- return self.session.scalar(stmt.limit(1)) is not None
- def list_by_demand_grade(
- self, biz_dt: str, source_demand_grade_id: int
- ) -> list[DemandVideoExpansion]:
- """按业务日与来源需求 id 查询拓展结果(未删除)。"""
- stmt = (
- select(DemandVideoExpansion)
- .where(
- DemandVideoExpansion.biz_dt == biz_dt,
- DemandVideoExpansion.source_demand_grade_id == int(source_demand_grade_id),
- DemandVideoExpansion.is_delete == 0,
- )
- .order_by(
- DemandVideoExpansion.video_id,
- DemandVideoExpansion.point_type,
- DemandVideoExpansion.id,
- )
- )
- return list(self.session.scalars(stmt).all())
- def count_distinct_videos_by_demand_grade(self, biz_dt: str) -> dict[int, int]:
- """按业务日统计每条需求的有效命中视频数。"""
- stmt = (
- select(
- DemandVideoExpansion.source_demand_grade_id,
- func.count(func.distinct(DemandVideoExpansion.video_id)),
- )
- .where(
- DemandVideoExpansion.biz_dt == biz_dt,
- DemandVideoExpansion.is_delete == 0,
- DemandVideoExpansion.video_id != "",
- DemandVideoExpansion.point_type.in_(("inspiration", "purpose", "key")),
- )
- .group_by(DemandVideoExpansion.source_demand_grade_id)
- )
- return {
- int(demand_grade_id): int(video_count or 0)
- for demand_grade_id, video_count in self.session.execute(stmt).all()
- }
- def bulk_upsert(self, rows: list[dict]) -> int:
- """按唯一键批量 upsert,冲突时更新 reason / point_desc。"""
- if not rows:
- return 0
- affected = 0
- for i in range(0, len(rows), _BATCH_SIZE):
- batch = rows[i : i + _BATCH_SIZE]
- stmt = insert(DemandVideoExpansion).values(batch)
- stmt = stmt.on_duplicate_key_update(
- reason=stmt.inserted.reason,
- point_desc=stmt.inserted.point_desc,
- run_id=stmt.inserted.run_id,
- is_delete=0,
- )
- result = self.session.execute(stmt)
- affected += result.rowcount or 0
- return affected
- class DemandVideoExpansionRunRepository(BaseRepository[DemandVideoExpansionRun]):
- """拓展任务执行记录 repository。"""
- model = DemandVideoExpansionRun
- def list_finished_grade_ids(self, biz_dt: str) -> set[int]:
- """返回指定业务日已成功完成拓展判断的 demand_grade.id 集合。"""
- stmt = select(DemandVideoExpansionRun.source_demand_grade_id).where(
- DemandVideoExpansionRun.biz_dt == biz_dt,
- DemandVideoExpansionRun.status == "finished",
- )
- return {int(v) for v in self.session.scalars(stmt).all() if v is not None}
- def upsert_run(
- self,
- *,
- biz_dt: str,
- run_id: str,
- source_demand_grade_id: int,
- saved_count: int,
- status: str = "finished",
- error_message: str | None = None,
- ) -> None:
- """记录单条需求的拓展判断完成状态。"""
- row = {
- "biz_dt": biz_dt,
- "run_id": run_id,
- "source_demand_grade_id": int(source_demand_grade_id),
- "saved_count": int(saved_count),
- "status": status,
- "error_message": error_message,
- }
- stmt = insert(DemandVideoExpansionRun).values(row)
- stmt = stmt.on_duplicate_key_update(
- run_id=stmt.inserted.run_id,
- saved_count=stmt.inserted.saved_count,
- status=stmt.inserted.status,
- error_message=stmt.inserted.error_message,
- )
- self.session.execute(stmt)
- def list_by_biz_dt(self, biz_dt: str) -> list[DemandVideoExpansionRun]:
- stmt = (
- select(DemandVideoExpansionRun)
- .where(DemandVideoExpansionRun.biz_dt == biz_dt)
- .order_by(DemandVideoExpansionRun.source_demand_grade_id)
- )
- return list(self.session.scalars(stmt).all())
- def get_by_demand_grade(
- self, biz_dt: str, source_demand_grade_id: int
- ) -> DemandVideoExpansionRun | None:
- stmt = select(DemandVideoExpansionRun).where(
- DemandVideoExpansionRun.biz_dt == biz_dt,
- DemandVideoExpansionRun.source_demand_grade_id == int(source_demand_grade_id),
- )
- return self.session.scalars(stmt).first()
|