扩展 Gordon Linoff 的评论和之前的答案:
SQL 数据库的功能有时会受到限制。由于您的字符串的顺序[String]
似乎并不重要,因此您正试图将类似 a 的内容set
放入关系数据库中,并且对于您的查询,您建议使用类似is a subset of
运算符的内容。
如果有一个提供这些结构的数据库引擎,那么使用它就没有错(我不知道)。但是,近似您的设置逻辑(或数据库本身不支持的任何逻辑)有缺点:
- 您必须明确处理边缘情况(参见 xnyhps 的回答)
- 您需要在代码中明确处理它,而不是隐藏存储数据的复杂性
- 您需要研究数据库引擎而不是编写 Haskell 代码
- 数据库和 Haskell 代码之间的接口变得模糊
一种更强大的方法是将您的存储任务重新定义为可以轻松融入关系数据库概念的内容。即尝试将其放在关系方面。实体和关系很简单,因此可以避免极端情况。您无需担心db 后端究竟如何存储您的数据。您根本不必为数据库操心。并且您的界面被简化为相当简单的查询(使用连接)。所有不能(比较)通过查询轻松实现的东西,都(可能)属于 Haskell 代码。
当然,具体情况根据具体情况而有所不同。
在您的特定情况下,您可以使用以下内容:
Table: Category
ID Description
0 math
1 algebra
2 personal
3 life
4 university
Table: CategoryGroup
ID CategoryID
0 0
0 1
1 2
1 3
2 1
2 4
2 2
...其中外键关系允许具有类别组。在这里,您正在使用它擅长的关系数据库。为了查询CategoryGroup
你将两个表连接起来,产生一个类型的结果
[(Entity CategoryGroup, Entity Category)]
我会在 Haskell 中将其转换为类似的东西
[(Entity CategoryGroup, [Entity Category])]
Category
为每个收集实体的位置CategoryGroup
(在您的 -Model 中需要deriving (Eq, Ord)
)CategoryGroup
。
对于给定的 List ,如上所述的集合逻辑cs :: [Entity Category]
将像
import qualified Data.Set as Set
import Data.Set (isSubsetOf)
let s = Set.fromList ["personal", "algebra"]
let s0 = Set.fromList $ map (categoryDescription . entityVal) cs
if s `isSubsetOf` s0 -- ... ?
刚开始习惯关系数据库的限制可能会很烦人。我想,对于最重要的事情(持久化数据)来说,一个健壮的概念通常比一个强大的概念更好,而且总是知道你的数据库在做什么是值得的。