【问题标题】:Persistent `upsert` isn't working持久的“upsert”不起作用
【发布时间】:2018-06-30 11:11:17
【问题描述】:

我显然对 Persistent 的 upsert 函数以及它如何与 Postgres 9.5 一起使用感到困惑。

我正在编写一个 Yesod 应用程序,它接收 JSON 值,解析它,然后在适当的数据库表上执行 upsert。我已经验证 JSON 被解析为有效值。见代码:

postITSClientsR :: Handler TypedContent
postITSClientsR = do
  i <- requireJsonBody :: Handler IntensiveTreatmentClient
  row <- runDB $ upsert i []
  selectRep . provideJson $ row

我还验证了此模型类型具有唯一性约束:

IntensiveTreatmentClient json
  clientId ClientId
  UniqueIntensiveTreatmentClientClientId clientId
  etc...

但是,我的新值没有得到保存。我已经验证了几次,但 Yesod 日志可能是最能说明问题的,因为它报告:

POST /api/itsClients
  Params: [("{\"clientId\":1,...","")]
  Request Body: {"clientId":1,...}
  Accept: */*
  Status: 200 OK 0.005041s

(字段已被有意删除以匿名化)通常,日志会报告已运行的 SQL 查询,而这不会报告任何内容。

发生了什么事? Yesod 或 Persistent 只是默默地删除我的查询,没有错误。

【问题讨论】:

  • 我认为这实际上不是upsert,而是repsert
  • @WillemVanOnsem 我不确定你的意思。 upsert 文档说 upsert 在第二个参数中传递了一个空列表(如在 upsert val [] 中)等价于使用唯一性约束作为键的 repsert
  • 无论如何,寻找响应正文的日志可能是个好主意。我们在这里只看到请求。例如,查询可能出错,但我们没有看到。
  • @WillemVanOnsem 好建议。响应正文未反映我尝试保存的更改。

标签: haskell yesod


【解决方案1】:

我认为 upsert 评论是错误。 我打开了拉取请求added: PersistentTest: upsert fail, it expected equivalent repsert by ncaq · Pull Request #821 · yesodweb/persistent

当两个参数列表为空时不更新。

如果你想要唯一的 repsert。 此代码由我创建,您可以使用堆栈溢出 cc 许可证。

-- | if a record exist by unique, then 'replace', else 'insert'
repsertBy :: ( PersistEntityBackend record ~ BaseBackend backend
             , PersistStoreWrite backend
             , PersistEntity record
             , PersistUniqueRead backend
             , MonadIO m) =>
             record -> ReaderT backend m (Key record)
repsertBy record = do
    me <- getByValue record
    case me of
        Nothing             -> insert record
        Just (Entity key _) -> replace key record >> return key

但是,此代码在 Yesod 主流中被拒绝。 因为,当存在多个唯一常量时,则未定义。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-22
    • 2020-02-05
    • 2012-07-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多