如何解决在 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 举报,一经查实,本站将立刻删除。