Внутреннее соединение в постоянном или я должен использовать 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 ]
Это работает, но извлечение списка уведомлений в виде списка и последующее использование его для выбора элементов в другой таблице... ну, это не совсем верно. Очевидно, что мне нужно здесь присоединиться, и тогда я смогу все эффективно обновить.
Как это сделать в чистом виде persistent
? Возможно ли и стоит ли в этом случае оставаться с persistent
для такого рода задач? Должен ли я использовать esqueleto
вместо? Похоже, мне нужно изучить различные DSL, чтобы работать с ним, поэтому я не уверен, переключаться или нет.
Как написать markAsRead
правильно с persistent
(если возможно)?
2 ответа
Как упоминал Грег, Эскелето - это путь. Вы можете попробовать прочитать документацию по основному модулю.
В настоящее время Esqueleto не поддерживает присоединения к UPDATE
s. Тем не менее, вы можете использовать подзапросы для того же эффекта.
Непроверенный код для начала работы:
-- | 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)
Да, Esqueleto, если вы хотите сделать присоединения. Persistent хорошо работает со встраиванием данных, если ваша БД и моделирование данных поддерживают это.