简体   繁体   English

内部加入持久性还是我应该使用 esqueleto?

[英]Inner join in persistent or should I use esqueleto?

I have this fragment describing Notification and Notified entities:我有这个片段描述NotificationNotified实体:

Notification
  type          NotiType
  release       ReleaseId
  date          UTCTime
Notified
  aboutWhat     NotificationId
  unread        Bool
  user          UserId

Now I want to write this:现在我想写这个:

-- | 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 ]

This works, but extracting list of notifications as list and then using it to select things in another table… well that's not exactly right.这是可行的,但是将通知列表提取为列表,然后使用它来选择另一个表中的内容……这并不完全正确。 Obviously I need a join here and then I will be able to update everything efficiently.显然我需要在这里加入,然后我将能够有效地更新所有内容。

How to do it in pure persistent ?persistent怎么做? Is it possible and is it a good idea in this case to stay with persistent for this sort of task?在这种情况下, persistent执行此类任务是否有可能?这是一个好主意吗? Should I use esqueleto instead?我应该改用esqueleto吗? It looks like I'll need to learn different DSL to work with it, so I'm not sure whether to switch or not.看起来我需要学习不同的 DSL 才能使用它,所以我不确定是否要切换。

How to write markAsRead properly with persistent (if possible)?如何使用persistent (如果可能)正确编写markAsRead

Yes Esqueleto if you want to do joins.是的,如果您想进行连接,则是 Esqueleto。 Persistent works well with embedding data if your DB and your data modelling support that.如果您的数据库和您的数据建模支持,持久性可以很好地嵌入数据。

As Greg mentioned, Esqueleto is the way to go.正如 Greg 所提到的,Esqueleto 是要走的路。 You can try reading its main module documentation .您可以尝试阅读其主要模块文档

Currently Esqueleto doesn't support joins on UPDATE s.目前 Esqueleto 不支持UPDATE的连接。 However, you can use subqueries to the same effect.但是,您可以使用子查询达到相同的效果。

Untested code to get you started:未经测试的代码可帮助您入门:

-- | 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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM