6

#Issue# 联表多字段的模糊查询tricks

 2 years ago
source link: https://lottewong.github.io/2022/01/30/%E8%81%94%E8%A1%A8%E5%A4%9A%E5%AD%97%E6%AE%B5%E7%9A%84%E6%A8%A1%E7%B3%8A%E6%9F%A5%E8%AF%A2tricks/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
#Issue# 联表多字段的模糊查询tricks
3 months ago 5 minutes read (About 689 words) 0 visits

#Issue# 联表多字段的模糊查询tricks

本文讨论联表多字段模糊查询的可能性,分为两种思路:

  1. 交给 dao layer 处理
  2. 交给 service layer 处理

需求

今天讨论一下看似简单实则繁琐的小需求——联表多字段的模糊查询。举个🌰:现在我要对超级管理员列表进行名字或描述的模糊查询,怎么实现?这里阻碍我们短平快地实现功能的点在于,超级管理员涉及三个表(用户表、角色表、用户-角色表),每个表还可能对多字段进行精确或模糊匹配,如果不先想清楚就开始动工,非常容易出现功能缺陷性能瓶颈🤦‍。

实现

交给 dao layer 处理

MySQL (Rational)

SELECT * FROM `user_role` AS `ur` 
FULL JOIN `users` on ur.user_id = users.user_id
FULL JOIN `roles` on ur.role_id = roles.role_id
SELECT * FROM `users` CONCAT(IFNULL(`user_name`,''),IFNULL(`user_desc`,'')) LIKE '%keyword%'

联表多字段的模糊查询

# tips:满足关系型的数据使用联表多字段的模糊查询可做到 SQL or ORM 一把梭
SELECT * FROM `user_role` AS `ur`
FULL JOIN `users` on ur.user_id = users.user_id
FULL JOIN `roles` on ur.role_id = roles.role_id
WHERE role_name=admin
CONCAT(IFNULL(`user_name`,''),IFNULL(`user_desc`,'')) LIKE ‘%keyword%’

MongoDB (Irrational)

db.users.aggregate({
"$lookup": {
from:'roles',
localField: 'role_id',
foreignField: '_id',
as: 'user_role'
}
})
db.users.find({
"$or": [
"user_name": {
"$regex": "keyword"
},
"user_desc": {
"$regex": "keyword"
}
]
})

联表多字段的模糊查询

// tips:不推荐非关系型用联表方法因为性能十分堪忧,更应该关注合理的数据结构设计
db.users.aggregate({
"$lookup": {
from:'roles',
localField: 'role_id',
foreignField: '_id',
as: 'user_role'
}
}, {
"$match": {
"$or": [
"user_name": {
"$regex": "keyword"
},
"user_desc": {
"$regex": "keyword"
}
]
}
})

交给 service layer 处理

// 数据库 I/O:3 times
// 空间复杂度:O(k)
// 时间复杂度:O(k × f)
// 其中,k 代表模糊搜索后的记录数量,f 代表条件过滤后的记录数量,k 和 f 在一般情况下是很小的
func FuzzySearch(keyword string) ([]rbac.User, error) {
var result []rbac.User

// 模糊搜索
// 空间复杂度↓,数据库 I/O ++
users, err := rbac.GetUserList(keyword)
if err != nil {
return nil, err
}
// 时间复杂度↑,O(k)
var userIds []string
for _, user := range users {
userIds = append(userIds, user.UserId)
}

// 精准匹配
// 空间复杂度=,数据库 I/O ++
role, err := rbac.GetRoleDetail(RoleNameAdmin)
if err != nil {
return nil, err
}
// 时间复杂度↑,O(1)
var roleIds []string
roleIds = append(roleIds, role.RoleId)

// 条件过滤
// 空间复杂度↓,数据库 I/O ++
urs, err := rbac.GetUserRoleList(userIds, roleIds)
if err != nil {
return nil, err
}
// 时间复杂度↑,O(k × f)
for _, user := range users {
for _, ur := range urs {
if user.UserId == ur.UserId {
result = append(result, user)
break
}
}
}

return result, nil
}

# Golang

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK