首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >将不同的对象模型作为参数传递给scala中的方法

将不同的对象模型作为参数传递给scala中的方法
EN

Stack Overflow用户
提问于 2017-11-21 18:12:54
回答 1查看 454关注 0票数 0

我一直在为scala中的类型关系以及如何有效地使用它们而奋斗。目前,我正试图了解如何使用它们只编辑蒙古族集合中的某些字段。这意味着将只包含这些字段的特定对象传递给(在阅读关于差异之后)我认为可以这样做的方法:

代码语言:javascript
代码运行次数:0
运行
复制
   abstract class DocClass
   case class DocPart1(oId: Option[BSONObjectID], name: String, other: String) extends DocClass
   case class DocPart2(city: String, country: String) extends DocClass

使用调用更通用方法的方法,如:

代码语言:javascript
代码运行次数:0
运行
复制
   def updateMultipleFields(oId: Option[BSONObjectID], dataModel: DocClass): Future[Result] = serviceClientDb.updateFields[T](collectionName, dataModel, oId)
   // updateFields updates the collection by passing *dataModel* into the collection, i.e. Json.obj("$set" -> dataModel)

所以dataModel可以是DocPart1DocPart2对象。我渴望不要在updateMultipleFields上使用类型参数(正如这个有趣的文章可能建议的那样),因为这将导致我在项目中的其他文件中将这些类型参数传递给这个方法时会遇到进一步的问题。我这样做是为了遵守DRY,并为了维护高效的数据库操作。

我绕着这个转了圈--有人能给我一点启示吗?

在@SerGr的评论之后编辑

所以说得很清楚,我使用的是Play/Scala/ReactiveMongo (作为记录在这里),我有一个包含很多字段的MongoDB集合。

代码语言:javascript
代码运行次数:0
运行
复制
   case class Doc(oId: Option[BSONObjectID], name: String, city: String, country: String, city: String, continent: String, region: String, region: String, latitude: Long, longitude: Long)

要创建一个新文档,我已经将Doc (上面)自动映射到集合结构(在Play -像这样中),并创建了一个表单(用于插入/更新集合)--所有操作都很好!

但是在编辑文档时,我只想更新一些字段(这样所有字段都不会更新)。因此,我创建了多个case classes,将这些字段划分为较小的模型(如DocPart1 &DocPart2的示例),并将表单数据映射到一个。这导致我将这些参数作为参数传递给updateMultipleFields方法,如上面所示。我希望这样做更有意义。

EN

回答 1

Stack Overflow用户

发布于 2017-11-23 20:41:59

我不确定我是否正确地理解了你的需要。这里还有一些可能是它的代码。假设我们的FullDoc类定义为:

代码语言:javascript
代码运行次数:0
运行
复制
case class FullDoc(_id: Option[BSONObjectID], name: String, other: String)

我们有两个部分更新,定义为:

代码语言:javascript
代码运行次数:0
运行
复制
sealed trait BaseDocPart

case class DocPart1(name: String) extends BaseDocPart

case class DocPart2(other: String) extends BaseDocPart

此外,假设我们有一个访问我们蒙古族藏品的人:

代码语言:javascript
代码运行次数:0
运行
复制
def docCollection: Future[JSONCollection] = ...

所以,如果我理解你的要求,你需要的是这样的东西:

代码语言:javascript
代码运行次数:0
运行
复制
def update[T <: BaseDocPart](oId: BSONObjectID, docPart: T)(implicit format: OFormat[T]) = {
  docCollection.flatMap(_.update(BSONDocument("_id" -> oId),
    JsObject(Seq("$set" -> Json.toJson(docPart)))))
}

本质上,主要的诀窍是使用通用的T <: BaseDocPart并传递implicit format: OFormat[T],这样即使在类型擦除之后,我们也可以将BaseDocPart的特定子级转换为JSON。

下面是一些额外的测试代码(我在控制台应用程序中使用了这些代码)

代码语言:javascript
代码运行次数:0
运行
复制
  implicit val fullFormat = Json.format[FullDoc]
  implicit val part1Format = Json.format[DocPart1]
  implicit val part2Format = Json.format[DocPart2]

  def insert(id: Int) = {
    val fullDoc = FullDoc(None, s"fullDoc_$id", s"other_$id")
    val insF: Future[WriteResult] = docCollection.flatMap(_.insert(fullDoc))
    val insRes = Await.result(insF, 2 seconds)
    println(s"insRes = $insRes")
  }

  def loadAndPrintAll() = {
    val readF = docCollection.flatMap(_.find(Json.obj()).cursor[FullDoc](ReadPreference.primaryPreferred).collect(100, Cursor.FailOnError[Vector[FullDoc]]()))
    val readRes = Await.result(readF, 2 seconds)
    println(s"readRes =\n${readRes.mkString("\n")}")
  }

  def loadRandomDocument(): FullDoc = {
    val readF = docCollection.flatMap(_.find(Json.obj()).cursor[FullDoc](ReadPreference.primaryPreferred).collect(100, Cursor.FailOnError[Vector[FullDoc]]()))
    val readRes = Await.result(readF, 2 seconds)
    readRes(Random.nextInt(readRes.length))
  }

  def updateWrapper[T <: BaseDocPart](oId: BSONObjectID, docPart: T)(implicit writer: OFormat[T]) = {
    val updateRes = Await.result(update(oId, docPart), 2 seconds)
    println(s"updateRes = $updateRes")
  }

  // pre-fill with some data    
  insert(1)
  insert(2)
  insert(3)
  insert(4)
  val newId: Int = ((System.currentTimeMillis() - 1511464148000L) / 100).toInt
  println(s"newId = $newId")

  val doc21: FullDoc = loadRandomDocument()
  println(s"doc21 = $doc21")
  updateWrapper(doc21._id.get, DocPart1(s"p1_modified_$newId"))

  val doc22: FullDoc = loadRandomDocument()
  println(s"doc22 = $doc22")
  updateWrapper(doc22._id.get, DocPart2(s"p2_modified_$newId"))

  loadAndPrintAll()
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/47419932

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档