3
考慮到以下兩種模式和GET /articles/:slug/comments
請求,我想根據其slug
檢索屬於文章的評論。如何使用Esqueleto做一個「SELECT ... IN(SELECT ...)」?
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_ operator,但我無法弄清楚如何使用它也不是,如果它比sub_select更合適。
我錯過了什麼?語法是否正確?謝謝。
無關,但'SELECT * ...'是一個糟糕的風格:)。爲什麼不使用SQLite或任何其他SQL DB?他們都很好打字;) – Igor
@Igor由不良風格你的意思是不只選擇什麼是必需的?根據你的第二個問題,我編輯了這個問題來指定我正在使用'persistent'和'postgresql'。 –
是的。爲什麼不在需要SQL時使用SQL? – Igor