Datomic中db.fn/cas的旧值是否允许使用查找引用?
关于Datomic
db.fn/cas 使用查找引用作为旧值失败的问题 嘿,这个坑我之前踩过!你的判断方向是对的——Datomic的db.fn/cas操作不允许用查找引用(比如[:task-state/name "locked"]这种形式)作为v-old参数,哪怕你确认这个查找引用对应的实体确实存在也不行。
为什么会报错?
Datomic里引用类型的属性(比如你的:task/state),实际存储的是关联实体的实体ID(EID),而不是查找引用向量。当你执行CAS时,Datomic会直接把你传入的v-old和属性当前存储的值做精确比对:
- 你传入的
v-old是[:task-state/name "locked"](一个向量) - 但属性当前的实际值是报错里显示的
17592186045558(一个数字EID)
两者类型和内容都不匹配,自然就触发了:db.error/cas-failed错误。
怎么解决?
你需要先查询出旧状态对应的实体ID,再把这个ID作为v-old传入CAS操作:
- 先执行查询获取旧状态的EID:
(def old-state-eid (d/q '[:find ?e . :where [?e :task-state/name "locked"]] your-db-connection)) - 然后用这个EID替换CAS里的查找引用:
(注:新值[[:db.fn/cas id :task/state old-state-eid [:task-state/name "pending"]]][:task-state/name "pending"]可以保留查找引用,Datomic会在事务中自动解析成对应的EID)
关键要点总结
db.fn/cas的v-old必须是属性当前存储的精确值:对于引用类型属性,就是关联实体的EID,不能用查找引用。- 新值
v支持使用查找引用,Datomic会自动解析,但旧值不支持这种语法。
内容的提问来源于stack exchange,提问作者Thomas Sonntag
相关产品推荐
相关产品推荐

