获取用户被授权的分级结构并支持分页查询需要考虑以下几个关键点: 1. 数据结构设计 - 如何表示分级结构 2. 权限验证 - 如何确定用户对各级节点的访问权限 3. 查询效率 - 如何高效获取数据并支持分页 4. 缓存策略 - 如何减少重复计算
推荐使用以下两种模型之一:
CREATE TABLE hierarchy (
id INT PRIMARY KEY,
name VARCHAR(100),
...其他属性
);
CREATE TABLE hierarchy_closure (
ancestor INT,
descendant INT,
depth INT,
PRIMARY KEY (ancestor, descendant),
FOREIGN KEY (ancestor) REFERENCES hierarchy(id),
FOREIGN KEY (descendant) REFERENCES hierarchy(id)
);
CREATE TABLE hierarchy (
id INT PRIMARY KEY,
name VARCHAR(100),
path VARCHAR(1000), -- 如 "/1/4/7/" 表示1→4→7
...其他属性
);
CREATE TABLE user_hierarchy_permission (
user_id INT,
node_id INT,
permission_type ENUM('read', 'write', 'admin'),
PRIMARY KEY (user_id, node_id),
FOREIGN KEY (node_id) REFERENCES hierarchy(id)
);
-- 获取用户有权限访问的节点及其子节点(分页)
SELECT h.*
FROM hierarchy h
JOIN hierarchy_closure hc ON h.id = hc.descendant
JOIN user_hierarchy_permission up ON up.node_id = hc.ancestor
WHERE up.user_id = ? AND up.permission_type = 'read'
GROUP BY h.id
ORDER BY h.id
LIMIT ? OFFSET ?;
-- 获取用户有权限访问的节点及其子节点(分页)
SELECT h.*
FROM hierarchy h
JOIN (
SELECT DISTINCT SUBSTRING_INDEX(SUBSTRING(h2.path, LENGTH(h1.path)), '/', 1) as node_id
FROM hierarchy h1
JOIN user_hierarchy_permission up ON up.node_id = h1.id
JOIN hierarchy h2 ON h2.path LIKE CONCAT(h1.path, '%')
WHERE up.user_id = ? AND up.permission_type = 'read'
) AS accessible_nodes ON accessible_nodes.node_id = h.id
ORDER BY h.id
LIMIT ? OFFSET ?;
索引优化:
缓存策略:
预计算:
分页优化:
def get_authorized_hierarchy(user_id, page=1, page_size=10):
# 检查缓存
cache_key = f"user_hierarchy:{user_id}:{page}:{page_size}"
cached = cache.get(cache_key)
if cached:
return cached
# 数据库查询
query = """
WITH RECURSIVE user_accessible_nodes AS (
-- 基础查询:用户直接有权限的节点
SELECT node_id FROM user_hierarchy_permission
WHERE user_id = %s AND permission_type = 'read'
UNION
-- 递归查询:所有子节点
SELECT hc.descendant
FROM user_accessible_nodes uan
JOIN hierarchy_closure hc ON hc.ancestor = uan.node_id
)
SELECT h.* FROM hierarchy h
JOIN user_accessible_nodes uan ON h.id = uan.node_id
ORDER BY h.id
LIMIT %s OFFSET %s
"""
offset = (page - 1) * page_size
results = db.execute(query, (user_id, page_size, offset))
# 设置缓存
cache.set(cache_key, results, timeout=300)
return results
选择具体实现方案时,应根据您的具体业务场景、数据规模和性能要求来决定。