【发布时间】:2020-05-20 01:24:31
【问题描述】:
我正在寻找一个很好的解决方案来构建和查询文档的索引存储,在我的例子中是“带有元数据的页面”。
我的页面有各种元数据字段,例如“标签”、“作者”等。
这样的页面可以这样建模
data Page =
Page { content :: Text
, tags :: [Text]
, authors :: [Text]
, score :: Int
, online :: Bool }
软件处理这样一个Pages的集合,需要通过这个集合进行查询。我当前的解决方案是为每个元数据字段手动处理Map,然后在创建新页面时手动填充每个映射(使用键映射 -> 设置页面)。然后对于我的应用程序的每个单独案例,我查询一个或多个 Map,交叉(或合并)结果,然后处理。这是乏味且容易出错的。
这就是为什么我想设计一个通用文档存储,有点像 Data.IxSet 提供的。请注意,我的问题是关于正确键入这样的商店,而不是关于使用 IxSet。
如果所有字段都有相同类型的键K(如Text),则可以键入这样的索引:Map Field (Map K (Set Page)),其中Field是字段的类型,例如
data Field = Tag | Author | ...
不幸的是,事实并非如此,字段键可以是 Text 或 Date 或 Int 或 Bool 等。它们都满足 Map 约束 Ord,所以这部分没有问题。
您将如何设计此数据类型并正确键入它,以便可以使用以下接口。我在不知道如何处理这些类型的地方打上了问号。这通常与正确处理可能是异构类型的集合有关。
data Field model key = Field { fieldId :: FieldId
, extractKeys :: model -> [key] }
-- initIndex create an index for values 'model' with descriptions for fields and keys extractors.
initIndex :: [Field model ?] -> Index ? model
-- adding a document to the index
addToIndex :: Index ? model -> model -> Index ? model
-- a request combines filters with boolean logic
data Request field ? = And [Request field ?] | Or [Request field ?] | Term (Filter field ?)
-- a filter is a constraint on a field keys. 'All' will intersect, 'Any' will unite ...
data Filter field k = All field [k] | Any field [k] | GreaterThan field k | LowerThan field k
queryIndex :: Index ? model -> Request field ? -> Set model
我希望这足够清楚,如果没有,我会根据需要进行更新。谢谢
【问题讨论】:
标签: haskell