从Haskell MongoDB驱动程序检索错误状态
我有一个MongoDB,其中有一个集合从Haskell MongoDB驱动程序检索错误状态,mongodb,haskell,error-handling,Mongodb,Haskell,Error Handling,我有一个MongoDB,其中有一个集合用户,其中包含电子邮件上的唯一索引: import Data.Bson (Value (Int32)) import Database.MongoDB (Index (..), createIndex, (=:)) createIndex $ Index "user" [ "email" =: Int32 1 ] "email" True False 我编写了一个函数,如果电子邮件地址未被使用,则插入新用户,如果电子邮件地址已被占用,则应失
用户
,其中包含电子邮件
上的唯一索引:
import Data.Bson (Value (Int32))
import Database.MongoDB (Index (..), createIndex, (=:))
createIndex $ Index "user" [ "email" =: Int32 1 ] "email" True False
我编写了一个函数,如果电子邮件地址未被使用,则插入新用户,如果电子邮件地址已被占用,则应失败:
import Data.Bson (Value (ObjId))
import Database.MongoDB (Action, ObjectId, (=:))
import qualified Database.MongoDB as M (insert)
data User = User
{ email :: Text
, firstName :: Text
, lastName :: Text
} deriving Show
data MongoEntity a = MongoEntity ObjectId a
createIfNotExists :: User
-> Action Handler (Either Text (MongoEntity User))
createIfNotExists (user@User {..}) = do
value <- M.insert "user" [ "email" =: email
, "firstName" =: firstName
, "lastName" =: lastName
]
case value of
ObjId objectId -> return (Right $ MongoEntity objectId user)
_ -> return $ Left "no document"
在
值之后,我从未使用过此模块,但阅读文档后,我能想到的最好方法是:
更改createIfNotExists
createIfNotExists :: MonadIO m =>
User -> Action m (Either String (MongoEntity User))
使用Control.Exception.Base
中的catchJust
。作者似乎不鼓励使用Control.Monad.Error.Class
main :: IO ()
main = do
pipe <- connect (host "127.0.0.1")
let user = User "jd@bar.baz" "John" "Doe"
eitherEntity <- catchJust writeFailureErrorStr
(access pipe master "user" $ createIfNotExists user)
(return . Left)
close pipe
writeFailureErrorStr :: Failure -> Maybe String
writeFailureErrorStr (WriteFailure _err str) = Just str
writeFailureErrorStr _other = Nothing
main::IO()
main=do
pipe根据Jean-Baptiste Potonnier的回答,在阅读了Michael Snoyman(和)的两篇文章后,我将代码改写如下:
import Control.Exception.Lifted (handleJust)
import Data.Bson (Value (ObjId))
import qualified Data.Bson as B (Value)
import qualified Data.Text as T (pack)
import Database.MongoDB (Action, Failure (..), (=:))
import qualified Database.MongoDB as M (insert)
createIfNotExists :: User -> Action Handler (Either Failure (MongoEntity User))
createIfNotExists user =
handleJust writeFailureHandler (return . Left) $ do
value <- insertUser user
return $
case value of
ObjId objectId -> Right $ MongoEntity (T.pack $ show objectId) user
_ -> error "Unexpected missing document"
where
writeFailureHandler :: Failure -> Maybe Failure
writeFailureHandler writeFailure@WriteFailure{} = Just writeFailure
writeFailureHandler _ = Nothing
insertUser :: User -> Action Handler B.Value
insertUser User{..} =
M.insert "users" [ "email" =: email
, "firstName" =: firstName
, "lastName" =: lastName
]
import Control.Exception.Lifted(handleJust)
导入数据.Bson(值(ObjId))
导入符合条件的数据。Bson为B(值)
导入符合条件的数据。文本为T(打包)
导入Database.MongoDB(操作、失败(..),(=:)
将符合条件的Database.MongoDB作为M导入(插入)
createIfNotExists::用户->操作处理程序(失败(MongoEntity用户))
createIfNotExists用户=
handleJust writeFailureHandler(return.Left)$do
value Right$MongoEntity(T.pack$show objectId)用户
_->错误“意外丢失文档”
哪里
writeFailureHandler::失败->可能失败
writeFailureHandlerwriteFailure@WriteFailure{}=刚刚写入文件
writeFailureHandler=无
insertUser::User->Action Handler B.值
插入器用户{..}=
M.插入“用户”[“电子邮件”=:电子邮件
,“firstName”=:firstName
,“lastName”=:lastName
]
使用该软件包。谢谢。我进一步阅读了库源代码,并倾向于捕捉异常。由于MongoDB不支持事务,使用find后跟insert会打开一个可能的争用条件。顺便说一句,以下是MongoDB错误代码列表:
import Control.Exception.Lifted (handleJust)
import Data.Bson (Value (ObjId))
import qualified Data.Bson as B (Value)
import qualified Data.Text as T (pack)
import Database.MongoDB (Action, Failure (..), (=:))
import qualified Database.MongoDB as M (insert)
createIfNotExists :: User -> Action Handler (Either Failure (MongoEntity User))
createIfNotExists user =
handleJust writeFailureHandler (return . Left) $ do
value <- insertUser user
return $
case value of
ObjId objectId -> Right $ MongoEntity (T.pack $ show objectId) user
_ -> error "Unexpected missing document"
where
writeFailureHandler :: Failure -> Maybe Failure
writeFailureHandler writeFailure@WriteFailure{} = Just writeFailure
writeFailureHandler _ = Nothing
insertUser :: User -> Action Handler B.Value
insertUser User{..} =
M.insert "users" [ "email" =: email
, "firstName" =: firstName
, "lastName" =: lastName
]