Commit 00673e17 authored by 375242562@qq.com's avatar 375242562@qq.com

fix: 批量/手动匹配排除同一试验已匹配患者,防止重复记录

matching_service.py:
- run_matching 改为 upsert:同一 (patient_id, trial_id) 存在记录时
  直接更新 LLM 结果,不再插入新行,彻底消除重复记录
- 仅首次匹配时向医生发送通知,重新匹配不重复推送

batch_matching_service.py:
- existing_pairs 查询从全表扫描改为按目标试验过滤,提升性能
- 只查 MatchingResult 的 patient_id/trial_id 列(select 子集)
Co-Authored-By: default avatarClaude Sonnet 4.6 <noreply@anthropic.com>
parent 0eda58d9
import asyncio import asyncio
from datetime import datetime from datetime import datetime
from sqlalchemy import select from sqlalchemy import select, tuple_
from app.database import AsyncSessionLocal from app.database import AsyncSessionLocal
from app.models.patient import Patient from app.models.patient import Patient
from app.models.trial import Trial, TrialStatus from app.models.trial import Trial, TrialStatus
...@@ -44,12 +44,14 @@ async def run_batch_matching(job_id: str) -> None: ...@@ -44,12 +44,14 @@ async def run_batch_matching(job_id: str) -> None:
) )
trials = trial_result.scalars().all() trials = trial_result.scalars().all()
# Build set of already-matched pairs to skip # Build set of already-matched pairs to skip(只查目标试验,避免全表扫描)
existing_result = await db.execute(select(MatchingResult)) trial_ids = [t.id for t in trials]
existing_pairs = { existing_result = await db.execute(
(r.patient_id, r.trial_id) select(MatchingResult.patient_id, MatchingResult.trial_id).where(
for r in existing_result.scalars().all() MatchingResult.trial_id.in_(trial_ids)
} )
)
existing_pairs = {(row.patient_id, row.trial_id) for row in existing_result.all()}
# Build work list (skip already matched pairs) # Build work list (skip already matched pairs)
pairs = [ pairs = [
......
...@@ -117,19 +117,41 @@ async def run_matching( ...@@ -117,19 +117,41 @@ async def run_matching(
} }
match_status = status_map.get(llm_result.get("overall_status", ""), MatchStatus.pending_review) match_status = status_map.get(llm_result.get("overall_status", ""), MatchStatus.pending_review)
matching_result = MatchingResult( # Upsert: 若该患者已对该试验有匹配记录,则更新而非新增
id=str(uuid.uuid4()), existing_stmt = select(MatchingResult).where(
patient_id=patient_id, MatchingResult.patient_id == patient_id,
trial_id=trial_id, MatchingResult.trial_id == trial_id,
status=match_status,
overall_score=llm_result.get("overall_score", 0.0),
criterion_details=llm_result.get("criteria_results", []),
evidence_spans=evidence_spans,
llm_model_used=settings.llm_model,
) )
db.add(matching_result) matching_result = (await db.execute(existing_stmt)).scalar_one_or_none()
is_new = matching_result is None
if matching_result:
matching_result.status = match_status
matching_result.overall_score = llm_result.get("overall_score", 0.0)
matching_result.criterion_details = llm_result.get("criteria_results", [])
matching_result.evidence_spans = evidence_spans
matching_result.llm_model_used = settings.llm_model
matching_result.matched_at = datetime.utcnow()
else:
matching_result = MatchingResult(
id=str(uuid.uuid4()),
patient_id=patient_id,
trial_id=trial_id,
status=match_status,
overall_score=llm_result.get("overall_score", 0.0),
criterion_details=llm_result.get("criteria_results", []),
evidence_spans=evidence_spans,
llm_model_used=settings.llm_model,
)
db.add(matching_result)
await db.flush() await db.flush()
# 仅首次匹配时向医生发送通知,避免重复推送
if not is_new:
await db.commit()
await db.refresh(matching_result)
return matching_result
# Determine recipient doctors by role # Determine recipient doctors by role
user_result = await db.execute( user_result = await db.execute(
select(User).options(selectinload(User.roles)).where(User.is_active == True) # noqa: E712 select(User).options(selectinload(User.roles)).where(User.is_active == True) # noqa: E712
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment