使用yesod的持久性选择列的子集

时间:2014-08-16 14:14:47

标签: mongodb haskell yesod persistent

我正在使用MongoDB持久化。 selectList查询返回完整的产品列表并将其加载到内存中;我想只返回一列的列。

Q1) 有没有办法只选择列的子集,以便可以加载更多的数据。为了更有效的查询?等效于mongoDB投影或SQL SELECT <col,col...> 也许类似于selectListCols函数,它也将属性列表作为参数,并返回列表类型的列值而不是实体值。

Q2) 如果没有,我不得不求助于手动Database.MongoDB查询,我可以在Persistent库中使用什么实用程序来修改selectList生成的mongodb查询,以便我可以向其添加mongodb投影并获取BSON值?

1 个答案:

答案 0 :(得分:1)

不,还没有办法做到这一点。持久性github页面上有一个未解决的问题。总结是作者正在等到ghc 7.10来实现某些东西。链接到open issueclosed duplicate

您可以使用原始驱动程序来实现查询。在库mongoDB中,请参阅Database.MongoDB.Query.Projector。在关闭的票证中,gregwebs建议&#34;持久性mongoDB中有很多助手现在使用原始驱动程序使用一些持久类型安全(fieldName肯定是你的预测朋友)&#34;

我不知道如何修改selectList生成的查询来执行投影。我怀疑使用当前的API有一种方法可以这样做,但我确信你可以使用修补的持久性来做到这一点。

以下是另一种解决方法:您是否考虑过定义不同的PersistEntity但保持集合名称相同? E.g。

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。如果您拥有包含许多字段的文档,并且您正试图从查询中挤出最后一滴性能,那么这可能是很多变种。
  • 您必须保持变体同步。
  • 转换。你如何&#down;&#39;一个类型安全,无样板的方式ThingSmallThing?例如。你手头有一个Thing并且你正在调用一个期望SmallThing
  • 的函数

您可以使用fromJSONtoJSON,但是aeson不支持ByteString,因此当您ByteString时,JSON不会有用第

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