我正在尝试让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))其次,什么是能力类型。理想情况下,我希望最终拥有Entity competenceId能力。
最后,如何在上面的连接中添加一个筛选器,以便只获取“user”的能力?
发布于 2012-07-20 08:29:33
我已经告诉过您,由于SelectOneMany使用的类型别名可能不是归纳的,因此不可能避免额外的类型签名;即,您的代码试图比其应有的多态程度更高,而类型签名对于限制这种多态是必要的。
你可以通过“从不同的角度”约束类型来避免使用巨大的签名,例如:
return (member, competences :: [(Entity User, [Entity UserCompetence])])由于类型别名User和UserCompetence选择特定的数据库后端,因此应该适当地解析这些类型。
另外,我刚刚为你破坏了competences的类型。哈哈!我希望这对你来说足够了。如果你想要一个多对多的三表连接,这样你就可以让一个用户拥有所有的能力,你无论如何都应该使用准备好的语句,因为潜在的AST开销,所以看看the generic raw SQL interface,它让你做传统的"SELECT * FROM foo WHERE bar = ?" [filteredBarValue],你可能更习惯使用它;它不像persistent的其余部分提供相同的类型安全性,但我认为这是在你的情况下实现三表连接的最简单的方法。
您可以通过修改User类型为OneFilterMany的oneFilterMany的结果来限制所选的OneFilterMany。就像这样(还没有测试过,但应该可以工作):
let join = (selectOneMany (UserCompetenceUser <-.) userCompetenceUser)
{ somFilterOne = [... filters for User ...] }
competences <- lift . runDB . runJoin $ join发布于 2012-07-21 03:37:41
多亏了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])https://stackoverflow.com/questions/11570800
复制相似问题