选择具有 yesod 持久性的列子集
Posted
技术标签:
【中文标题】选择具有 yesod 持久性的列子集【英文标题】:Select subset of columns with yesod's persistent 【发布时间】:2014-08-16 14:14:46 【问题描述】:我在 MongoDB 中使用持久性。 selectList
查询返回完整的产品列表并将它们加载到内存中;我只想返回列的一个子集。
Q1)
有没有办法只选择列的子集以便加载更多数据。为了更有效的查询?等效于 mongoDB 投影或 SQL SELECT <col,col...>
可能类似于 selectListCols 函数,它也将属性列表作为参数,并返回列表类型的列值而不是实体值。
Q2) 如果没有,我必须求助于手动 Database.MongoDB 查询,我可以从 Persistent 库中使用什么实用程序来修改由 selectList 生成的 mongodb 查询,以便我可以向其中添加 mongodb 投影并获取 BSON 值?
【问题讨论】:
【参考方案1】:不,目前还没有办法做到这一点。持久性的 github 页面上有一个未解决的问题。总结是作者正在等到 ghc 7.10 来实现一些东西。链接到open issue 和closed duplicate。
您可以使用原始驱动程序来实现您的查询。在库 mongoDB 中,请参阅 Database.MongoDB.Query.Projector。在已关闭的票证中,gregwebs 建议“persistent-mongoDB 现在有很多帮助者可以在原始驱动程序中使用一些持久类型安全(fieldName 肯定会成为你的预测朋友)”
我不知道如何修改 selectList 生成的查询来执行投影。我怀疑当前的 API 是否有办法做到这一点,但我相信你可以通过修补持久性做到这一点。
这是另一种解决方法:您是否考虑过定义不同的PersistEntity
s 但保持集合名称相同?例如
let mongoSettings = (mkPersistSettings (ConT ''MongoBackend)) mpsGeneric = False
in share [mkPersist mongoSettings, mkMigrate "migrateAll"][persistUpperCase|
Thing sql=thing_collection
name String
stuff [Int32]
deriving Show
SmallThing sql=thing_collection
name String
deriving Show
|]
请注意,sql=thing_collection
用于强制两个 PersistEntity 引用同一个 MongoDB 集合。
此解决方法有一些折衷:
优点:
类型系统清楚地表明了查询将返回哪些字段。返回SmallThing
的查询显然不包含stuff
。这使得进行查询并省略您稍后要阅读的字段成为编译时错误。
缺点:
您必须为每个变体定义一个PersistEntity
。如果您的文档包含许多字段,并且您试图从查询中挤出最后一滴性能,那可能会有很多变体。
您必须使变体保持同步。
转换。你如何以一种类型安全、无样板的方式将Thing
“向下转换”为SmallThing
?例如。您手头有一个 Thing
,并且您正在调用一个需要 SmallThing
的函数。
你可以使用fromJSON
和toJSON
,但是aeson不支持ByteString
s,所以当你有ByteString
s时,JSON就没有用了。
另外,请查看 toPersistFields
和 fromPersistFields
。也许它们可以用来代替 JSON。
【讨论】:
以上是关于选择具有 yesod 持久性的列子集的主要内容,如果未能解决你的问题,请参考以下文章