微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在 Go 应用程序中使用 Cassandra 插入前检查行是否存在

如何解决在 Go 应用程序中使用 Cassandra 插入前检查行是否存在

我正在将 gocql 与我的 Go 应用程序一起使用,并试图解决下面描述的问题。

CREATE TABLE IF NOT EXISTS website.users (
    id            uuid,email_address text,first_name    text,last_name     text,created_at    timestamp,PRIMARY KEY (email_address)
);

查询将覆盖匹配记录,这是 Cassandra 的预期行为。

INSERT INTO users (id,email_address,first_name,last_name,created_at)
VALUES (?,?,?)

为了防止覆盖现有记录,我们可以在查询结束时使用 IF NOT EXISTS

INSERT INTO users (id,?)
IF NOT EXISTS

但是,我无法知道查询是否影响了数据库中的任何行。不知何故,我需要将诸如“记录存在”之类的消息返回给调用者,但目前这是不可能的。如果 session.Query(...).Exec() 有特定的东西,它会很有用,但据我所知还没有。

如果没有匹配的记录,我想在继续 SELECT 之前通过 email_address INSERT 但你可以猜到这是不可行的,因为当我 {{1} }在 INSERT 之后创建了一条新记录,其他一些操作可能会SELECT创建一条具有相同电子邮件地址的新记录。

我们如何处理这种情况?

解决方法

解决方案是使用 ScanCAS,库中的测试用例示例是 here

注意

  • ScanCAS() 中字段的顺序应与 cqlsh> DESCRIBE keyspace.users; 块的 CREATE TABLE ... 输出匹配。
  • 如果您不关心扫描的字段,请改为使用 MapScanCAS
func (r Repository) Insert(ctx context.Context,user User) error {
    var (
        emailAddressCAS,firstNameCAS,idCAS,lastNameCAS string
        createdAtCAS                                      time.Time
    )

    query := `
INSERT INTO users (email_address,created_at,first_name,id,last_name)
VALUES (?,?,?) IF NOT EXISTS
`

    applied,err := r.session.Query(
        query,user.EmailAddress,user.CreatedAt,user.FirstName,user.LastName,user.CreateAt,).
    WithContext(ctx).
    ScanCAS(&emailAddressCAS,&createdAtCAS,&firstNameCAS,&idCAS,&lastNameCAS)

    if err != nil {
        return err
    }
    if !applied {
        // Check CAS vars here if you want.
        return // your custom error implying a duplication
    }

    return nil
}
,

如果您将 INSERT 与 IF NOT EXISTS 一起使用,那么与不返回任何内容的“正常”插入相比,此类查询返回的单行结果包括:

  • 名称为 [applied] 的字段,值为真 - 如果之前没有记录,并且插入了新行
  • 名称为 [applied] 的字段,值为假值 + 现有行的所有列。

因此,您只需要获取插入查询的结果并对其进行分析。有关详情,请参阅 documentation

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。