2012-07-19 67 views
3

我试图让selectOneMany工作取得有限的成功。selectOneMany Yesod持久

我有以下的数据库模型

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)) 

其次;什么是能力类型。理想情况下,我想结束[实体competencyId能力]。

最后;如何将一个过滤器添加到上面的连接中,以便仅获取“用户”的权限?

回答

2

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

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

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

由于类型别名UserUserCompetence选择一个特定的数据库后端的类型,应妥善解决。

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

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

let join = (selectOneMany (UserCompetenceUser <-.) userCompetenceUser) 
      { somFilterOne = [... filters for User ...] } 
competences <- lift . runDB . runJoin $ join 
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])