在 Persistent (Haskell) 中,如何插入不存在的记录?

In Persistent (Haskell), how can I insert a record only if it doesn't already exist?

我是 Haskell 初学者,请提前致歉!

我一直在关注 the Persistent tutorial here

我有一个具有唯一性约束的数据模型:

Book
    gutId Int
    UniqueGutId gutId
    ...
    author [AuthorId]
    ... 
Author
    gutId Int
    UniqueAuthorGutId gutId
    ...

当我去 insert 一条记录时使用这个:

  runSqlite "test.db" $ do
    runMigration migrateAll

    -- FIXME: This won't work if there's an author that's already in the database.
    authorIds <- mapM insert authors

如果该记录已经在数据库中,则无法使用。 (这只是 return 一个例外。)我可以这样做:

authorIds <- mapM insertUnique authors

但问题是,我稍后需要使用authorIds来更新Book记录。所以我只是想知道是否有人知道一种简单的方法来插入记录(如果它不存在)和 return 新密钥,或者如果它已经存在则获取记录密钥,以便我有一个数组无论哪种方式的钥匙。 The full code at this point is up here.

您只需执行您自己提到的两个操作:

authorIds <- forM authors $ \a -> do
    res <- insertUnique a
    case res of
        Just key -> return key
        _ -> fromJust <$> getBy (authorGutId a)

怎么样

authorIds <- mapM (fmap (either entityKey id) . insertBy) authors

insertBy :: _ => -- some constraints
            record -> -- given some record, try to insert it
            _ ( -- in some monad
               Either (Entity record) (Key record)
               -- if found: Left existing
               -- otherwise: Right newKey
              )
Data.Either.either :: (l -> o) -> (r -> o) -> Either l r -> o
-- eliminator for Either
-- purpose and implementation completely determined by type

我们使用insertBy尝试插入记录。 fmap 在 monad 下钻取,either entityKey id 提取 Key.