Case class with Id with reactivemongo, 应该是可选的或必需的

Case class with Id with reactivemongo, should be optional or required

我正在为 play scala 中的用户构建以下 api:

case class User(_id: BSONObjectId, username: String)

问题是,当客户端向 store/create 新用户发送请求时,_id 不存在。

一个可行的解决方案似乎是:

case class User(_id: Option[BSONObjectId], username: String)

但是,不仅为了插入用户,还要检查其他 CRUD 操作的选项字段似乎有点烦人。

我得到的一个建议是有两种类型:

case class User(name: String) ; type UserWithId = (Id, User)

case class User[A](id: A, name: String); type UserWithId = User[BSONObjectId]
type UserWithoutId = User[Unit]

我选择了后者,因为它看起来很合适。 我创建了适当的 Json 格式来处理这两种情况插入和其他操作:

object User {
  lazy val userWithIdFormat: OFormat[UserWithId] = Json.format[UserWithId]
  lazy val userWithoutIdFormat: OFormat[UserWithoutId] = Json.format[UserWithoutId]
}

但是,现在我在插入时遇到了一个问题,如何在生成Id后从UserWithoutId => UserwithId优雅地转换

所以下一步就是创建这个方法:

case class User[A](_id: A, username: String)
{
  def map[B](f: A => B): User[B] = ???
}

这是我需要实现的某种类型的 Monad 吗? (刚学范畴论)

我想最简单的方法是添加一个 "initialized/empty" 状态,其中 Class 需要始终有一个 Id,并且只有当它持久存在时才会有用户名。 像 val initalizedUser = User(BSONObjectId.generate(), "")

最好的方法是什么? 使用类型会提高性能并使领域更丰富,或者只是添加一个状态会让未来的同事更容易接近

map 的实现是什么,这是我应该提取的东西并拥有我自己的 Monad 实现以应用于所有未来的集合吗?

是否最好使用功能库来解决这个问题?

在我看来,在这里使用复杂类型似乎没有必要:它不会提高性能,并且可能会使一些不熟悉这些概念的同事感到困惑。

我最喜欢的方法是有两种情况 classes,一种用于用户创建,一种用于表示创建的实体:

case class CreateUser(username: String)

case class User(id: BSONObjectId, username: String)

这有几个优点:

  • 表达用户意图
  • CreateUser 案例 class
  • 中,您可以在两个实体中使用不同的字段并进行更复杂的验证
  • 未来会更有保障

缩减是需要多写一个案例class,但是在scala中很容易