选择具有 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 是否有办法做到这一点,但我相信你可以通过修补持久性做到这一点。

这是另一种解决方法:您是否考虑过定义不同的PersistEntitys 但保持集合名称相同?例如

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 的函数。

你可以使用fromJSONtoJSON,但是aeson不支持ByteStrings,所以当你有ByteStrings时,JSON就没有用了。

另外,请查看 toPersistFieldsfromPersistFields。也许它们可以用来代替 JSON。

【讨论】:

以上是关于选择具有 yesod 持久性的列子集的主要内容,如果未能解决你的问题,请参考以下文章

Yesod 持久代码的类型类约束

yesod 持久性依赖缺失

yesod 持久性:从键列表中获取实体列表

Yesod 持久示例

Yesod 数据库持久记录访问

yesod 持久:在小村庄内获取实体值