2012-07-19 64 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])