selectOneMany Yesod Persistent

时间:2012-07-19 23:30:03

标签: haskell yesod

我试图让selectOneMany在有限​​的成功下工作。

我有以下数据库模型

User
 email Text
 verkey Text Maybe
 verified Bool
 password Text Maybe
 UniqueUser email
 date UTCTime
 deriving Show

Competence
 parent CompetenceId Maybe
 title Text
 UniqueCompetence title
 deriving Show Read

UserCompetence
 competence CompetenceId
 user UserId Eq
 UniqueUserCompetence user competence
 deriving Show Read
来自我的处理程序的

代码

mmember <- runMaybeT $ do
  id <- MaybeT $ maybeAuth
  user <- MaybeT . runDB . get . entityKey $ id
  Entity memberId member <- MaybeT . runDB . getBy . UniqueMember . userEmail $ user
  competences <- lift . runDB . runJoin $ (selectOneMany (UserCompetenceUser <-.) userCompetenceUser)
  return (member,competences)

第一个;我无法在没有添加大类型签名的情况下运行此代码,这应该是它吗?

competences <- lift . runDB . runJoin $ (selectOneMany (UserCompetenceUser <-.) userCompetenceUser :: SelectOneMany SqlPersist (UserGeneric SqlPersist) (UserCompetenceGeneric SqlPersist))

其次;什么是能力类型。理想情况下,我希望最终获得[实体能力的能力]。

最后;如何为上述联接添加过滤器,以便仅获得“用户”的权限?

2 个答案:

答案 0 :(得分:2)

我已经告诉过你,由于SelectOneMany使用的类型别名可能不是归纳的,因此无法避免额外的类型签名;即你的代码试图比它应该更多态,并且类型签名是限制多态性所必需的。

您可以通过“从不同的角度”约束类型来避免使用巨大的签名,例如:

return (member, competences :: [(Entity User, [Entity UserCompetence])])

由于类型别名UserUserCompetence选择了特定的数据库后端,因此应该适当地解析类型。

另外,我只是为你破坏了competences的类型。哈!我希望这对你来说已经足够了。如果你想直接进行多对多三表连接,以便你可以获得用户“拥有”的所有权限,你应该使用预备语句,因为可能存在AST开销,所以请查看the generic raw SQL interface哪个让您可以使用您可能更习惯使用的传统"SELECT * FROM foo WHERE bar = ?" [filteredBarValue];它不提供与persistent的其余部分相同的类型安全性,但我认为这是在您的情况下实现三表连接的最简单方法。

您可以通过修改类型为User的{​​{1}}的结果来限制所选的oneFilterMany。像这样(没有测试过,但应该工作):

OneFilterMany

答案 1 :(得分:2)

感谢来自dflemstr的(很多)帮助,我最终得到了

mmember <- runMaybeT $ do
  id <- MaybeT $ maybeAuth
  let user = entityVal id
  Entity memberId member <- MaybeT . runDB . getBy . UniqueMember . userEmail $ user
  let competenceStatement =
        Text.concat
        [ "SELECT ?? "
        , "FROM   competence,     user_competence "
        , "WHERE  competence.id = user_competence.competence_id "
        , "AND    ?             = user_competence.user_id"
        ]
  competences <- lift . runDB $ rawSql competenceStatement
                 [toPersistValue . entityKey $ id]
  return (member, competences :: [Entity Competence])