【发布时间】:2018-03-12 02:32:51
【问题描述】:
我正在考虑一个当前的问题——当你在树上搜索每个节点的 ACL 时总是会发生这种情况——如果用户请求分页结果,我有时必须检索原始结果,过滤ACL,如果我没有足够的结果,我必须再次搜索......直到我有足够的结果。
一次性搞定不是更好吗?
鉴于此(为简洁起见,我跳过索引):
CREATE DATABASE `test`;
CREATE TABLE `acl` (
`id` varchar(36) NOT NULL,
`entry_id` varchar(36) NOT NULL,
`principal_id` varchar(36) NOT NULL,
`recursive` tinyint(1) NOT NULL,
`permission` varchar(45) NOT NULL,
PRIMARY KEY (`id`),
KEY `fk_entry_has_acl_idx` (`entry_id`),
CONSTRAINT `fk_entry_has_acl` FOREIGN KEY (`entry_id`) REFERENCES `entry` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `entry` (
`id` varchar(36) NOT NULL,
`parent_id` varchar(36) DEFAULT NULL,
`path` varchar(512) DEFAULT NULL,
`name` varchar(128) DEFAULT NULL,
`type` varchar(45) DEFAULT NULL,
`category` varchar(45) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
此语句是否(跳过任何实际搜索条件):
SELECT
e.*
FROM
entry e JOIN acl a JOIN entry e2 ON
((
e.id = a.entry_id
AND
a.recursive=0
) OR (
a.entry_id = e2.id
AND
e.path LIKE CONCAT(e2.path,'%')
AND
a.recursive=1
))
AND
a.principal_id in ("K")
AND
a.permission IN ("READ","WRITE")
GROUP BY e.id;
成为我正在寻找的陈述?你能发现任何明显的改进和/或错误吗?我对那里的 CONCAT 语句有点不满意......有没有办法避免这种情况?
编辑:ID 是 UUID,“路径”字段将一直包含父 ID,如下所示:
c83eff41-dec8-45fb-94ef-6e3f380ebcec.1db333d9-995e-4e24-af8a-da2faf962060.dd71fd12-c975-4f33-bf0e-2df9da312bcd
【问题讨论】:
-
你应该在
%之前有目录分隔符,这样你就不会匹配相似但没有嵌套的路径。 -
@barmar 你说的有点对,但我使用的是 UUID,而且我使用的是 UUID 中的路径,而不是名称。无论如何它们都是固定长度的。所以我真的不希望那里有任何碰撞。我将在问题中添加此约束。