Skip to content

Commit a2d1a9d

Browse files
committed
improve: Support similarity sorting across account, name, and email fields
1 parent b99f140 commit a2d1a9d

1 file changed

Lines changed: 33 additions & 2 deletions

File tree

backend/apps/system/api/user.py

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,14 +82,31 @@ async def pager(
8282

8383
# 相似度排序:精确匹配 > 前缀匹配 > 包含匹配
8484
# 当有 keyword 时,将 similarity_score 加入 SELECT 列以满足 DISTINCT 约束
85+
# 对 account、name、email 三个字段分别计算相似度,取最高(最小值)
8586
similarity_score = None
8687
if keyword:
87-
similarity_score = case(
88+
from sqlalchemy import func
89+
# 每个字段的相似度分数
90+
account_score = case(
8891
(UserModel.account == keyword, 0),
8992
(UserModel.account.startswith(keyword), 1),
9093
(UserModel.account.contains(keyword), 2),
9194
else_=3
9295
)
96+
name_score = case(
97+
(UserModel.name == keyword, 0),
98+
(UserModel.name.startswith(keyword), 1),
99+
(UserModel.name.contains(keyword), 2),
100+
else_=3
101+
)
102+
email_score = case(
103+
(UserModel.email == keyword, 0),
104+
(UserModel.email.startswith(keyword), 1),
105+
(UserModel.email.contains(keyword), 2),
106+
else_=3
107+
)
108+
# 取三个字段中的最小值(最高匹配度)
109+
similarity_score = func.LEAST(account_score, name_score, email_score)
93110
select_columns.append(similarity_score.label('similarity_score'))
94111

95112
origin_stmt = (
@@ -133,12 +150,26 @@ async def pager(
133150
)
134151
# 第二次查询也需要应用相同的相似度排序
135152
if keyword:
136-
similarity_score = case(
153+
from sqlalchemy import func
154+
account_score = case(
137155
(UserModel.account == keyword, 0),
138156
(UserModel.account.startswith(keyword), 1),
139157
(UserModel.account.contains(keyword), 2),
140158
else_=3
141159
)
160+
name_score = case(
161+
(UserModel.name == keyword, 0),
162+
(UserModel.name.startswith(keyword), 1),
163+
(UserModel.name.contains(keyword), 2),
164+
else_=3
165+
)
166+
email_score = case(
167+
(UserModel.email == keyword, 0),
168+
(UserModel.email.startswith(keyword), 1),
169+
(UserModel.email.contains(keyword), 2),
170+
else_=3
171+
)
172+
similarity_score = func.LEAST(account_score, name_score, email_score)
142173
stmt = stmt.order_by(similarity_score, sort_clause)
143174
else:
144175
stmt = stmt.order_by(sort_clause)

0 commit comments

Comments
 (0)