docs+feat: matches 唯一键语义明确化 + source_event_id partial unique
docs/05-data.md:业务唯一=同联赛同主客同自然天; source_event_id 用于统计回填与血缘,新增部分唯一索引说明与 upsert 查找顺序。 新增 ix_matches_source_event_id_unique(WHERE IS NOT NULL), 兼容存量空值历史行;MatchRepository.find_by_source_event_id; events upsert 优先按 event_id 定位,回退自然键。 迁移 0021 + 回归测试修复(find_by_source_event_id 方法调用误判)。
This commit is contained in:
@@ -80,6 +80,20 @@ class MatchRepository:
|
||||
)
|
||||
return (await self._session.execute(stmt)).scalars().all()
|
||||
|
||||
async def find_by_source_event_id(self, source_event_id: int) -> Match | None:
|
||||
"""按上游 event id 查找比赛(唯一命中,用于 upsert 优先路径)。
|
||||
|
||||
source_event_id 上有 partial unique 索引(WHERE IS NOT NULL),
|
||||
同联赛同主客同天(自然键)与上游 event_id 共同保障同一场比赛
|
||||
重复采集时 upsert 而非插入重复行。
|
||||
"""
|
||||
stmt = (
|
||||
select(Match)
|
||||
.options(selectinload(Match.stats))
|
||||
.where(Match.source_event_id == source_event_id)
|
||||
)
|
||||
return (await self._session.execute(stmt)).scalar_one_or_none()
|
||||
|
||||
async def find_finished_with_stats(self, league_ids: list[int], *, limit: int) -> list[Match]:
|
||||
"""已完赛且有上游 event id 的比赛(按日期倒序),供统计回填逐场拉取。
|
||||
|
||||
|
||||
Reference in New Issue
Block a user