[英]Haskell Esqueleto project subset of columns to list of custom records
在所有示例中,我看到esqueleto的結果被投影到元組列表或實體記錄中 。
例如:
previousLogItems <- select $ from $ \li -> do
orderBy [desc (li ^. LogItemId)]
limit 10
return (li ^. LogItemId, li ^. LogItemTitle)
在esqueleto中是否有任何方法可以將列的子集投影到自定義記錄(不同於實體)而不是元組? 這樣做沒有從元組到自定義記錄的額外投影。
例如,假設從數據庫中獲取所有數據是低效的,因此我們只想將數據庫中的WindowTitle和BeginTime列投影到具有足夠名稱的自定義記錄中。
更新
不工作代碼的示例:
data Custom = Custom
{ title :: Text
, id :: Int
} deriving (Eq, Show, Generic)
daily :: Servant.Handler [Custom]
daily = do
lis <- liftIO $ runDB $
select $ from $ \li -> do
orderBy [desc (li ^. LogItemId)]
limit 25
return (Custom (li ^. LogItemTitle) (li ^. LogItemId))
return lis
錯誤:
• Couldn't match expected type ‘Text’
with actual type ‘SqlExpr (Database.Esqueleto.Value Text)’
• In the first argument of ‘Custom’, namely ‘(li ^. LogItemTitle)’
In the first argument of ‘return’, namely
‘(Custom (li ^. LogItemTitle) (li ^. LogItemId))’
In a stmt of a 'do' block:
return (Custom (li ^. LogItemTitle) (li ^. LogItemId))
更新
不工作代碼的示例:
daily :: Servant.Handler [Custom]
daily = do
lis <- liftIO $ runDB $
select $ from $ \li -> do
orderBy [desc (li ^. LogItemId)]
limit 25
return (Custom <$> (li ^. LogItemTitle) <*> (li ^. LogItemId))
return lis
錯誤:
• Couldn't match type ‘Database.Esqueleto.Value Text’ with ‘Text’
Expected type: SqlExpr Text
Actual type: SqlExpr (Database.Esqueleto.Value Text)
• In the second argument of ‘(<$>)’, namely ‘(li ^. LogItemTitle)’
In the first argument of ‘(<*>)’, namely
‘Custom <$> (li ^. LogItemTitle)’
In the first argument of ‘return’, namely
‘(Custom <$> (li ^. LogItemTitle) <*> (li ^. LogItemId))’
• Couldn't match type ‘Database.Esqueleto.Value (Key LogItem)’
with ‘Int’
Expected type: SqlExpr Int
Actual type: SqlExpr (Database.Esqueleto.Value (Key LogItem))
• In the second argument of ‘(<*>)’, namely ‘(li ^. LogItemId)’
In the first argument of ‘return’, namely
‘(Custom <$> (li ^. LogItemTitle) <*> (li ^. LogItemId))’
In a stmt of a 'do' block:
return (Custom <$> (li ^. LogItemTitle) <*> (li ^. LogItemId))
esqueleto實際上在這里做的事情有點復雜。 以下是select
的類型:
select :: (SqlSelect a r, MonadIO m) => SqlQuery a -> SqlReadT m [r]
這需要一個SqlQuery a
(一個monad包裝你return
的值),並返回一個SqlReadT m [r]
(包含結果列表的monad)。 return
Custom
類型時,會發生以下情況:
a
類型轉換為持久性的內部SQL表示 [r]
要使這適用於自定義類型,您需要實例化SqlSelect ,並定義與持久類型之間的轉換函數:
data Custom' = Custom' (Value Text) (Value Int)
data Custom = Custom
{ title :: Text
, id :: Int
}
instance SqlSelect Custom' Custom where
sqlSelectCols esc (Custom' a b) = (mconcat [ta, ", ", tb], va ++ vb)
where
(ta, va) = sqlSelectCols esc a
(tb, vb) = sqlSelectCols esc b
sqlSelectColCount _ = 2
sqlSelectProcessRow [PersistText a, PersistInt64 b] = Right $ Custom a b
sqlSelectProcessRow _ = Left "Error: Incorrect rows to translate to Custom"
(請注意,我實際上無法測試上述任何內容,因此可能存在錯誤)
需要注意的一點是,在上面的例子中, a
和r
類型不相同( Custom'
與Custom
)。 這是因為在select
,您使用的所有值都是Value
類型,而不是它們的實際類型。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.