Как сделать "SELECT ... IN (SELECT ...)" с помощью Esqueleto?
Учитывая следующие две модели и 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
Используя постоянство 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.
Что мне не хватает? Правильный ли синтаксис? Благодарю.
1 ответ
Вы хотите что-то вроде этого
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