简体   繁体   English

使用yesod持续执行“加入”的正确方法

[英]Correct way to do a “join” in persist with yesod

Consider the models: 考虑一下模型:

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

and the function 和功能

getGamingSessionsR :: Handler RepHtml
getGamingSessionsR = do
  sessions <- runDB $ selectList [GamingSessionEnd ==. Nothing] [Desc GamingSessionTable]
  defaultLayout $(widgetFile ("opensessions"))

how would one go about getting all of the Player names for each of the associated sessions? 如何获得每个相关会话的所有播放器名称?

doing

players <- runDB $ selectList [FilterOr . map (\(Entity _ s) -> PlayerId ==. (GamingSessionPlayer s)) $ sessions] []

gets the list of players; 得到球员名单; but it isn't associated with the sessions at all 但它根本与会话无关

There is limited join support in persistent at this time, and I believe it is SQL only. 目前持久性的连接支持有限,我相信它只是SQL。

I have a couple of helpers which I use for simple cases. 我有几个帮助我用于简单的情况。 They can be found here . 他们可以在这里找到。 It's not a true JOIN, it selects once per table then builds a list of tuples representing "joined" rows with an element from each. 这不是一个真正的JOIN,它每个表选择一次,然后构建一个元组列表,表示“连接”行,每个元素都包含一个元素。

Given your models and that helper, you should able to do something like: 鉴于你的模型和助手,你应该做的事情如下:

records <- runDB $ do
    sessions <- selectList [] []
    players  <- selectList [] []
    tables   <- selectList [] []

    return $ joinTables3 gamingSessionPlayer gamingSessionTable sessions players tables

forM records $ \(session, player, table) -> do
    --
    -- ...
    --

Only cases where a record exists in all three tables will be returned (so it's an INNER JOIN), but you might want to pre-filter for efficiency too. 只有在所有三个表中都存在记录的情况才会被返回(因此它是一个内部联接),但您可能也希望对效率进行预过滤。

For future reference, for sql you can use esqueleto or rawSQL to do joins - see this answer Baffled by selectOneMany in Yesod 为了将来的参考,对于s​​ql,您可以使用esqueleto或rawSQL来进行连接 - 请参阅此答案 YesO中的selectOneMany困惑

If you wanted to use a join, in esqueleto your query would look something like: 如果您想使用连接,请在esqueleto中查询,如下所示:

select $ from $ \(gamingSession `InnerJoin` player) -> do 
    on (gamingSession ^. GamingSessionPlayer ==. player ^. PlayerId)
    where_ $ isNothing $ gamingSession ^. GamingSessionEnd
    orderBy [asc (gamingSession ^. GamingSessionTable)] 
    return (gamingSession, player ^. PlayerId)

This would return a (Entity GamingSession, PlayerId) tuple 这将返回(Entity GamingSession,PlayerId)元组

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM