geo*_*off 8 haskell persistent yesod
考虑一下模型:
Player
name Text
nick Text
email Text Maybe
phone Text Maybe
note Textarea Maybe
minutes Int Maybe
deriving
Table
name Text
game Text
pointsHour Int
seats Int Maybe
description Text Maybe
deriving
GamingSession
start UTCTime
end UTCTime Maybe
player PlayerId
table TableId
seat Int Maybe
deriving
Run Code Online (Sandbox Code Playgroud)
和功能
getGamingSessionsR :: Handler RepHtml
getGamingSessionsR = do
sessions <- runDB $ selectList [GamingSessionEnd ==. Nothing] [Desc GamingSessionTable]
defaultLayout $(widgetFile ("opensessions"))
Run Code Online (Sandbox Code Playgroud)
如何获得每个相关会话的所有播放器名称?
干
players <- runDB $ selectList [FilterOr . map (\(Entity _ s) -> PlayerId ==. (GamingSessionPlayer s)) $ sessions] []
Run Code Online (Sandbox Code Playgroud)
得到球员名单; 但它根本与会话无关
目前持久性的连接支持有限,我相信它只是SQL.
我有几个帮助我用于简单的情况.他们可以在这里找到.这不是一个真正的JOIN,它每个表选择一次,然后构建一个元组列表,表示"连接"行,每个元素都包含一个元素.
鉴于你的模型和助手,你应该做的事情如下:
records <- runDB $ do
sessions <- selectList [] []
players <- selectList [] []
tables <- selectList [] []
return $ joinTables3 gamingSessionPlayer gamingSessionTable sessions players tables
forM records $ \(session, player, table) -> do
--
-- ...
--
Run Code Online (Sandbox Code Playgroud)
只有在所有三个表中都存在记录的情况才会被返回(因此它是一个内部联接),但您可能也希望对效率进行预过滤.
为了将来参考,对于 sql,您可以使用 esqueleto 或 rawSQL 进行连接 - 请参阅此答案Baffled by selectOneMany in Yesod
如果您想使用连接,在 esqueleto 中,您的查询将类似于:
select $ from $ \(gamingSession `InnerJoin` player) -> do
on (gamingSession ^. GamingSessionPlayer ==. player ^. PlayerId)
where_ $ isNothing $ gamingSession ^. GamingSessionEnd
orderBy [asc (gamingSession ^. GamingSessionTable)]
return (gamingSession, player ^. PlayerId)
Run Code Online (Sandbox Code Playgroud)
这将返回一个 (Entity GamingSession, PlayerId) 元组