【问题标题】:Yesod/Persistent one-to-one queryYesod/持久的一对一查询
【发布时间】:2012-03-12 09:27:02
【问题描述】:

说,在 Yesod/Persistent 中,我有这样的模型设置:

User
    ident Text
    password Text Maybe
    UniqueUser ident
Question
    title Text
    asker UserId Eq

我有一个Questions 的列表,并且想检索Users 的相应列表。我该怎么做呢?

我考虑过加入,但这些是一对多的,而不是一对一的(我想没关系,但我想要一个更简单的解决方案)。手动加入也是一种选择,但我担心性能 - 我有

questions <- runDB $ selectList [QuestionTitle !=. ""] [LimitTo 10]
let askerIds = map (\(Entity _ q) -> questionAsker q) questions
askers <- sequence $ map (runDB . get) askerIds
let questionsAndAskers = zip questions askers

但我担心在map 中使用runDB(它不会为每个用户向数据库发出单独的请求吗?)

有没有更好/更惯用的方法来实现这一点?

【问题讨论】:

  • 是的,我认为可以公平地假设每次您点击runDB,都会执行另一个数据库查询。

标签: haskell yesod


【解决方案1】:

我还没有对此进行类型检查,但我会将整个内容粘贴到 runDB 中:

runDB $ selectList [QuestionTitle !=. ""] [LimitTo 10] >>= mapM (\qe@(Entity _ q) -> do
    asker <- get $ questionAsker q
    return (qe, asker))

【讨论】:

  • 那么持久化会有 N+1 个选择而不是 1 个?
  • 是的,按照配方。如果您想要一个查询,则需要使用联接。为此,我建议使用 esqueleto。
  • 感谢 esqeleto 看起来很有希望
【解决方案2】:

怎么样:

questions <- runDB $ selectList [QuestionTitle !=. ""] [LimitTo 10]
let askerIds = map (\(Entity _ q) -> questionAsker q) questions
askers <- runDB $ selectList [UserId <-. askerIds] []
let questionsAndAskers = zip questions askers

这似乎应该为用户访问一次数据库。

【讨论】:

  • 如果我没记错的话,第二行可以写成let askersIds = map (questionAsker . entityVal) questions,我觉得这样更易读。
猜你喜欢
  • 2017-04-07
  • 2014-05-09
  • 1970-01-01
  • 2012-10-18
  • 1970-01-01
  • 1970-01-01
  • 2013-03-09
  • 2013-09-05
  • 1970-01-01
相关资源
最近更新 更多