【问题标题】:Correct way to do a "join" in persist with yesod坚持使用 yesod 进行“加入”的正确方法
【发布时间】:2012-04-04 11:23:18
【问题描述】:

考虑模型:

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

和功能

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

如何获取每个关联会话的所有玩家名称?

在做

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

获取玩家列表;但它根本与会话无关

【问题讨论】:

    标签: haskell persistent yesod


    【解决方案1】:

    目前持久化的连接支持有限,我相信它只是SQL。

    我有几个助手用于简单的情况。他们可以找到here。这不是真正的 JOIN,它为每个表选择一次,然后构建一个表示“连接”行的元组列表,每个行都有一个元素。

    鉴于您的模型和那个助手,您应该能够执行以下操作:

    records <- runDB $ do
        sessions <- selectList [] []
        players  <- selectList [] []
        tables   <- selectList [] []
    
        return $ joinTables3 gamingSessionPlayer gamingSessionTable sessions players tables
    
    forM records $ \(session, player, table) -> do
        --
        -- ...
        --
    

    只有在所有三个表中都存在一条记录的情况下才会返回(因此它是一个 INNER JOIN),但您可能也希望进行预过滤以提高效率。

    【讨论】:

    • 我们支持一对多的连接,它在 SQL 连接和应用程序连接方面都实现了,因此它可以用于 SQL 或 NoSQL 后端。现在记录很差,但希望可以尽快解决。
    • 我不认为在 Haskell 中加入一个 RDBMS 应该首先做的事情可以被认为是一个可以接受的答案。特别是对于 Haskell 所在的世界/社区。​​span>
    【解决方案2】:

    为了将来参考,对于 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)
    

    这将返回一个 (Entity GamingSession, PlayerId) 元组

    【讨论】:

      猜你喜欢
      • 2020-07-13
      • 2014-10-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多