内部加入持久性还是我应该使用 esqueleto?
Inner join in persistent or should I use esqueleto?
我有这个描述 Notification
和 Notified
实体的片段:
Notification
type NotiType
release ReleaseId
date UTCTime
Notified
aboutWhat NotificationId
unread Bool
user UserId
现在我想写这个:
-- | Mark specified notification as already seen by specific user. Note that
-- we use 'ReleaseId' to select notification, so this may result in several
-- notifications marked as “read” if they happen to be about the same
-- release. This is generally what you want.
markAsRead
:: ReleaseId -- ^ Release in question
-> UserId -- ^ User who has seen mentioned release
-> SqlPersistM ()
markAsRead release user = do
ns <- selectKeysList [ NotificationRelease ==. release ] []
updateWhere [ NotifiedAboutWhat <-. ns
, NotifiedUnread ==. True
, NotifiedUser ==. user ]
[ NotifiedUnread =. False ]
这行得通,但是将通知列表提取为 list,然后将其用于 select 另一个 table 中的内容……这并不完全正确。显然我需要在这里加入,然后我才能有效地更新所有内容。
纯persistent
怎么做?在这种情况下,使用 persistent
完成此类任务是否可能并且是个好主意?我应该改用 esqueleto
吗?看来我需要学习不同的 DSL 才能使用它,所以我不确定是否要切换。
如何用 persistent
正确地写 markAsRead
(如果可能的话)?
是的,如果您想加入 Esqueleto。如果您的数据库和数据建模支持 嵌入 数据,则持久性效果很好。
正如 Greg 所说,Esqueleto 是必经之路。您可以尝试阅读 its main module documentation.
目前 Esqueleto 不支持 UPDATE
上的联接。但是,您可以使用子查询来达到相同的效果。
未经测试的入门代码:
-- | Mark specified notification as already seen by specific user. Note that
-- we use 'ReleaseId' to select notification, so this may result in several
-- notifications marked as “read” if they happen to be about the same
-- release. This is generally what you want.
markAsRead
:: ReleaseId -- ^ Release in question
-> UserId -- ^ User who has seen mentioned release
-> SqlPersistM ()
markAsRead release user =
update $ \n -> do
set n [ NotifiedUnread =. val False ]
where_ $
n ^. NotifiedUnread ==. val True &&.
n ^. NotifiedUser ==. val user &&.
n ^. NotifiedAboutWhat `in_`
(subList_select $
from $ \t -> do
where_ $ t ^. NotificationRelease ==. val release
return $ t ^. NotificationId)
我有这个描述 Notification
和 Notified
实体的片段:
Notification
type NotiType
release ReleaseId
date UTCTime
Notified
aboutWhat NotificationId
unread Bool
user UserId
现在我想写这个:
-- | Mark specified notification as already seen by specific user. Note that
-- we use 'ReleaseId' to select notification, so this may result in several
-- notifications marked as “read” if they happen to be about the same
-- release. This is generally what you want.
markAsRead
:: ReleaseId -- ^ Release in question
-> UserId -- ^ User who has seen mentioned release
-> SqlPersistM ()
markAsRead release user = do
ns <- selectKeysList [ NotificationRelease ==. release ] []
updateWhere [ NotifiedAboutWhat <-. ns
, NotifiedUnread ==. True
, NotifiedUser ==. user ]
[ NotifiedUnread =. False ]
这行得通,但是将通知列表提取为 list,然后将其用于 select 另一个 table 中的内容……这并不完全正确。显然我需要在这里加入,然后我才能有效地更新所有内容。
纯persistent
怎么做?在这种情况下,使用 persistent
完成此类任务是否可能并且是个好主意?我应该改用 esqueleto
吗?看来我需要学习不同的 DSL 才能使用它,所以我不确定是否要切换。
如何用 persistent
正确地写 markAsRead
(如果可能的话)?
是的,如果您想加入 Esqueleto。如果您的数据库和数据建模支持 嵌入 数据,则持久性效果很好。
正如 Greg 所说,Esqueleto 是必经之路。您可以尝试阅读 its main module documentation.
目前 Esqueleto 不支持 UPDATE
上的联接。但是,您可以使用子查询来达到相同的效果。
未经测试的入门代码:
-- | Mark specified notification as already seen by specific user. Note that
-- we use 'ReleaseId' to select notification, so this may result in several
-- notifications marked as “read” if they happen to be about the same
-- release. This is generally what you want.
markAsRead
:: ReleaseId -- ^ Release in question
-> UserId -- ^ User who has seen mentioned release
-> SqlPersistM ()
markAsRead release user =
update $ \n -> do
set n [ NotifiedUnread =. val False ]
where_ $
n ^. NotifiedUnread ==. val True &&.
n ^. NotifiedUser ==. val user &&.
n ^. NotifiedAboutWhat `in_`
(subList_select $
from $ \t -> do
where_ $ t ^. NotificationRelease ==. val release
return $ t ^. NotificationId)