gpt4 book ai didi

sql - 编写 Database.Esqueleto 查询、条件连接和计数

转载 作者:行者123 更新时间:2023-12-01 20:13:10 27 4
gpt4 key购买 nike

我怎样才能写作Database.Esqueleto以模块化方式进行查询,这样在定义“基本”查询和相应的结果集之后,我可以通过添加额外的内部联接和 where 表达式来限制结果集。

此外,如何将返回实体(或字段元组)列表的基本查询转换为对结果集进行计数的查询,因为基本查询不是这样执行的,而是使用 LIMIT 和 LIMIT 对其进行修改的版本偏移。

以下错误的 Haskell 代码片段采用自 the Yesod Book希望能澄清我的目标。

{-# LANGUAGE QuasiQuotes, TemplateHaskell, TypeFamilies, OverloadedStrings #-}
{-# LANGUAGE GADTs, FlexibleContexts #-}
import qualified Database.Persist as P
import qualified Database.Persist.Sqlite as PS
import Database.Persist.TH
import Control.Monad.IO.Class (liftIO)
import Data.Conduit
import Control.Monad.Logger
import Database.Esqueleto
import Control.Applicative

share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persistLowerCase|
Person
name String
age Int Maybe
deriving Show
BlogPost
title String
authorId PersonId
deriving Show
Comment
comment String
blogPostId BlogPostId
|]

main :: IO ()
main = runStdoutLoggingT $ runResourceT $ PS.withSqliteConn ":memory:" $ PS.runSqlConn $ do
runMigration migrateAll

johnId <- P.insert $ Person "John Doe" $ Just 35
janeId <- P.insert $ Person "Jane Doe" Nothing

jackId <- P.insert $ Person "Jack Black" $ Just 45
jillId <- P.insert $ Person "Jill Black" Nothing

blogPostId <- P.insert $ BlogPost "My fr1st p0st" johnId
P.insert $ BlogPost "One more for good measure" johnId
P.insert $ BlogPost "Jane's" janeId

P.insert $ Comment "great!" blogPostId

let baseQuery = select $ from $ \(p `InnerJoin` b) -> do 
on (p ^. PersonId ==. b ^. BlogPostAuthorId)
where_ (p ^. PersonName `like` (val "J%"))
return (p,b)

-- Does not compile
let baseQueryLimited = (,) <$> baseQuery <*> (limit 2)

-- Does not compile
let countingQuery = (,) <$> baseQuery <*> (return countRows)

-- Results in invalid SQL
let commentsQuery = (,) <$> baseQuery
<*> (select $ from $ \(b `InnerJoin` c) -> do
on (b ^. BlogPostId ==. c ^. CommentBlogPostId)
return ())

somePosts <- baseQueryLimited
count <- countingQuery
withComments <- commentsQuery
liftIO $ print somePosts
liftIO $ print ((head count) :: Value Int)
liftIO $ print withComments
return ()

最佳答案

查看文档和select的类型:

select :: (...) => SqlQuery a -> SqlPersistT m [r]

很明显,在调用 select 后,我们离开了纯可组合查询 (SqlQuery a) 的世界,并进入了副作用的世界 (SqlPersistT m [ r])。因此,我们只需要在选择之前进行组合即可。

let baseQuery = from $ \(p `InnerJoin` b) -> do 
on (p ^. PersonId ==. b ^. BlogPostAuthorId)
where_ (p ^. PersonName `like` (val "J%"))
return (p,b)

let baseQueryLimited = do r <- baseQuery; limit 2; return r
let countingQuery = do baseQuery; return countRows

somePosts <- select baseQueryLimited
count <- select countingQuery

这适用于限制和计数。我还没弄清楚如何进行连接,但看起来应该是可能的。

关于sql - 编写 Database.Esqueleto 查询、条件连接和计数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16595892/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com