From 678136a9563ae3a423c2504cf2c1d7b0c565a3a1 Mon Sep 17 00:00:00 2001 From: ulleo Date: Mon, 29 Sep 2025 21:58:49 +0800 Subject: [PATCH] fix: check exists terminology --- backend/apps/terminology/curd/terminology.py | 91 +++++++++++++++++--- backend/locales/en.json | 3 +- backend/locales/ko-KR.json | 1 + backend/locales/zh-CN.json | 1 + 4 files changed, 81 insertions(+), 15 deletions(-) diff --git a/backend/apps/terminology/curd/terminology.py b/backend/apps/terminology/curd/terminology.py index a8bc52d8c..f5a382eba 100644 --- a/backend/apps/terminology/curd/terminology.py +++ b/backend/apps/terminology/curd/terminology.py @@ -226,6 +226,10 @@ def create_terminology(session: SessionDep, info: TerminologyInfo, oid: int, tra specific_ds = info.specific_ds if info.specific_ds is not None else False datasource_ids = info.datasource_ids if info.datasource_ids is not None else [] + if specific_ds: + if not datasource_ids: + raise Exception(trans("i18n_terminology.datasource_cannot_be_none")) + parent = Terminology(word=info.word, create_time=create_time, description=info.description, oid=oid, specific_ds=specific_ds, datasource_ids=datasource_ids) @@ -237,8 +241,37 @@ def create_terminology(session: SessionDep, info: TerminologyInfo, oid: int, tra else: words.append(child) - exists = session.query( - session.query(Terminology).filter(and_(Terminology.word.in_(words), Terminology.oid == oid)).exists()).scalar() + # 基础查询条件(word 和 oid 必须满足) + base_query = and_( + Terminology.word.in_(words), + Terminology.oid == oid + ) + + # 构建查询 + query = session.query(Terminology).filter(base_query) + + if specific_ds: + # 仅当 specific_ds=False 时,检查数据源条件 + query = query.where( + or_( + or_(Terminology.specific_ds == False, Terminology.specific_ds.is_(None)), + and_( + Terminology.specific_ds == True, + Terminology.datasource_ids.isnot(None), + text(""" + EXISTS ( + SELECT 1 FROM jsonb_array_elements(datasource_ids) AS elem + WHERE elem::text::int = ANY(:datasource_ids) + ) + """) # 检查是否包含任意目标值 + ) + ) + ) + query = query.params(datasource_ids=datasource_ids) + + # 转换为 EXISTS 查询并获取结果 + exists = session.query(query.exists()).scalar() + if exists: raise Exception(trans("i18n_terminology.exists_in_db")) @@ -277,6 +310,13 @@ def update_terminology(session: SessionDep, info: TerminologyInfo, oid: int, tra if count == 0: raise Exception(trans('i18n_terminology.terminology_not_exists')) + specific_ds = info.specific_ds if info.specific_ds is not None else False + datasource_ids = info.datasource_ids if info.datasource_ids is not None else [] + + if specific_ds: + if not datasource_ids: + raise Exception(trans("i18n_terminology.datasource_cannot_be_none")) + words = [info.word] for child in info.other_words: if child in words: @@ -284,22 +324,45 @@ def update_terminology(session: SessionDep, info: TerminologyInfo, oid: int, tra else: words.append(child) - exists = session.query( - session.query(Terminology).filter( - Terminology.word.in_(words), - Terminology.oid == oid, + # 基础查询条件(word 和 oid 必须满足) + base_query = and_( + Terminology.word.in_(words), + Terminology.oid == oid, + or_( + Terminology.pid != info.id, + and_(Terminology.pid.is_(None), Terminology.id != info.id) + ), + Terminology.id != info.id + ) + + # 构建查询 + query = session.query(Terminology).filter(base_query) + + if specific_ds: + # 仅当 specific_ds=False 时,检查数据源条件 + query = query.where( or_( - Terminology.pid != info.id, - and_(Terminology.pid.is_(None), Terminology.id != info.id) - ), - Terminology.id != info.id - ).exists()).scalar() + or_(Terminology.specific_ds == False, Terminology.specific_ds.is_(None)), + and_( + Terminology.specific_ds == True, + Terminology.datasource_ids.isnot(None), + text(""" + EXISTS ( + SELECT 1 FROM jsonb_array_elements(datasource_ids) AS elem + WHERE elem::text::int = ANY(:datasource_ids) + ) + """) # 检查是否包含任意目标值 + ) + ) + ) + query = query.params(datasource_ids=datasource_ids) + + # 转换为 EXISTS 查询并获取结果 + exists = session.query(query.exists()).scalar() + if exists: raise Exception(trans("i18n_terminology.exists_in_db")) - specific_ds = info.specific_ds if info.specific_ds is not None else False - datasource_ids = info.datasource_ids if info.datasource_ids is not None else [] - stmt = update(Terminology).where(and_(Terminology.id == info.id)).values( word=info.word, description=info.description, diff --git a/backend/locales/en.json b/backend/locales/en.json index 79c4c6f40..049c47aa6 100644 --- a/backend/locales/en.json +++ b/backend/locales/en.json @@ -40,11 +40,12 @@ }, "i18n_terminology": { "terminology_not_exists": "Terminology does not exists", + "datasource_cannot_be_none": "Datasource cannot be none or empty", "cannot_be_repeated": "Term name, synonyms cannot be repeated", "exists_in_db": "Term name, synonyms exists" }, "i18n_data_training": { - "datasource_cannot_be_none": "Datasource cannot be none", + "datasource_cannot_be_none": "Datasource cannot be none or empty", "data_training_not_exists": "Example does not exists", "exists_in_db": "Question exists" }, diff --git a/backend/locales/ko-KR.json b/backend/locales/ko-KR.json index 59f561895..b426ecc35 100644 --- a/backend/locales/ko-KR.json +++ b/backend/locales/ko-KR.json @@ -40,6 +40,7 @@ }, "i18n_terminology": { "terminology_not_exists": "용어를 찾을 수 없습니다", + "datasource_cannot_be_none": "데이터 소스를 선택해 주세요", "cannot_be_repeated": "용어 이름과 동의어는 중복될 수 없습니다", "exists_in_db": "용어 이름 또는 동의어가 이미 존재합니다" }, diff --git a/backend/locales/zh-CN.json b/backend/locales/zh-CN.json index 963ea8382..010943d06 100644 --- a/backend/locales/zh-CN.json +++ b/backend/locales/zh-CN.json @@ -40,6 +40,7 @@ }, "i18n_terminology": { "terminology_not_exists": "该术语不存在", + "datasource_cannot_be_none": "数据源不能为空", "cannot_be_repeated": "术语名称,同义词不能重复", "exists_in_db": "术语名称,同义词已存在" },