3

考虑以下两个模型和一个GET /articles/:slug/comments请求,我想检索属于一篇文章的评论,基于它的slug.

Article json sql=articles
    slug        Slug
    title       Text
    description Text
    body        Text
    createdAt   UTCTime default=now()
    updatedAt   UTCTime Maybe default=NULL
    userId      UserId
    UniqueSlug  slug

Comment json sql=comments
    body      Text
    createdAt UTCTime default=now()
    updatedAt UTCTime Maybe default=NULL
    articleId ArticleId
    userId    UserId

使用persistence's rawSql,我们可以如下完成

getCommentsForArticle :: Slug -> App (Cmts [Entity Comment])
getCommentsForArticle slug = do
    comments <- runDb $ rawSql stm [toPersistValue slug]
    return (Cmts comments)
        where stm = "SELECT ?? FROM comments \
                    \WHERE article_id IN (\
                        \SELECT id FROM articles WHERE slug = ?)"

但是,鉴于我想维护 Haskell 和 SQL 之间的类型安全,我想使用esqueleto. 这是我正在努力的部分。通过阅读文档,sub_select似乎是完成这项工作的工具。这是我所拥有的:

getCommentsForArticle :: Slug -> App (Cmts [Comment])
getCommentsForArticle slug = do
    comments <- E.select $
        E.from $ \cmts -> do
            let subQuery =
                    E.from $ \arts -> do
                        E.where_ $ arts ^. ArticleSlug ==. E.val slug
                        return (arts ^. ArticleId)
            E.where_ $ cmts ^. CommentArticleId ==. E.sub_select subQuery
            return cmts
    return $ Cmts comments

我也注意到in_ 运算符,但我不知道如何使用它,也不知道它是否比sub_select更合适。

我错过了什么?语法是否正确?谢谢。

4

1 回答 1

0

你会想要这样的东西

getCommentsForArticle slug = do
  c <- select $ from $ \cmts -> do
         let a = subList_select $ from $ \arts -> do
                 where_ $ arts ^. ArticleSlug ==. val slug
                 return $ arts ^. ArticleId
         where_ $ cmts ^. CommentArticleId `in_` a
         return cmts
  return $ Cmts c
于 2018-01-11T09:26:07.697 回答