即使 cardinality/one 枚举类型也不会覆盖

enumerated types not overwriting even though cardinality/one

在编写评级系统时,我希望人们能够对 post 进行评级,但我只希望每个用户有一个评级。

所以在我的模式中我有类似的东西

{:db/id #db/id[:db.part/db -1] 
 :db/ident :rating/value
 :db/valueType :db.type/ref
 :db/cardinality :db.cardinality/one  <<thinking this serves a purpose
 :db/doc "rating applied to this particular post"
 :db.install/_attribute :db.part/db}

{:db/id #db/id[:db.part/user -2] 
 :db/ident :rating.value/verypositive}

{:db/id #db/id[:db.part/user -3]
 :db/ident :rating.value/positive}

{:db/id #db/id[:db.part/user -4]
 :db/ident :rating.value/needswork}

我只希望每封电子邮件在任何时候都可以访问一个评级,但我有点难过。

当我向 post

提交多个评分时
>(add-rating-to-post 1759 "so@gm.co" "verypositive")
>(add-rating-to-post 1759 "so@gm.co" "needswork")
>(add-rating-to-post 1759 "so@gm.co" "positive")
>(add-rating-to-post 1759 "so@gm.co" "verypositive")

交易工作正常,但当我查询附加到特定 post-eid 的评级时,我得到类似

的信息
({:bid 1759,
  :rating :rating.value/verypositive
  :email "sova@web"}
 {:bid 1759,
  :rating :rating.value/positive,
  :email "sova@web"}
 {:bid 1759,
  :rating :rating.value/needswork,
  :email "sova@web"})

真的,我只想要最新的,所以返回一个用户提交的所有评分列表(最后 x 个)会很棒。

...但它会填充,直到每个枚举类型都有一个,然后忽略添加。

关于我如何实现我所追求的行为有什么建议吗?

非常感谢

你的架构目前基本上是说你只允许一个值 per rating.value

我建议 'single rating per user' 不应是架构约束,而应是域级问题 - 实现此问题的适当方法是允许 多个评级 每个 post 每个用户,然后编写一个交易函数来检查用户之前是否评价过 post 并且再次 deny 评价,或者 收回旧评级(取决于你想要的行为)。

您还希望将评级本身视为一个实体,如果您还没有这样做的话。这样您就拥有 :rating/post :ref:rating/value :ref:rating/email 属性,并为每个评分创建一个新实体。

您的架构是正确的。您使用 idents 进行枚举是正确的。

不是每次都创建一个新的评级实体,而是使用查询来检查是否已经有一个具有评级 :bid 和评级用户 :email 的实体。如果是这样,请使用 :db/add 断言处理新的 :rating 属性(不要担心撤回,它们是为 :cardinality/one 属性隐式创建的)。如果没有,请像您已经在做的那样创建一个。

如果您需要自动执行,例如。 G。为了避免同一用户在竞争条件下对一篇文章创建两个评级实体,您需要通过编写和使用 database function.

在事务处理程序中完成所有这些工作

如果您需要查看用户给出的所有评分,请使用 history database 等功能查询实体的 :rating 值如何随时间变化。