简体   繁体   English

MongoDB Scala 驱动程序。 如何仅更新案例 class object 中更改的文档字段

[英]MongoDB Scala driver. How to update only changed document's fields from the case class object

I have the following case class:我有以下案例 class:

  @GQLDirective(federation.Key("User Config"))
case class UserConfig(
                        userId: Int,
                        personalGroup: Option[PersonalGroup] = None,
                        accountGroup: Option[AccountGroup] = None
                       ) extends Bson {
    override def toBsonDocument[TDocument](documentClass: Class[TDocument], codecRegistry: CodecRegistry): BsonDocument = {
      new BsonDocumentWrapper[UserConfig](this, codecRegistry.get(classOf[UserConfig]))
    }
  }

And trying to update an already stored document this way:并尝试以这种方式更新已存储的文档:

def update(userConfig: UserConfig) = {
    collection.updateOne(equal("userId", 1), userConfig).headOption()
  }

But when I am trying to do so I have the following error: Invalid BSON field name userId但是当我尝试这样做时,出现以下错误: Invalid BSON field name userId

I have also tried to use replaceOne method, but it will replace the whole object and erase the fields that I don't want to.我也尝试过使用 replaceOne 方法,但它会替换整个 object 并删除我不想删除的字段。

What I am trying to achieve: I want to save only changed fields in mongodb document.我想要实现的目标:我只想保存 mongodb 文档中更改的字段。 These fields are given by graphql request这些字段由 graphql 请求给出

For now, I found a way to convert and recursively merge new object with old ones like this.现在,我找到了一种方法来转换和递归合并新的 object 和这样的旧的。 If somebody has a better code or opinion - I will be happy to chat如果有人有更好的代码或意见 - 我会很乐意聊天

val firstJson =  parse(userConfigFromRequest.toBsonDocument(classOf[UserConfig], codecRegistry).toJson).extract[Map[String, Any]]
val secondJson = parse(config.toBsonDocument(classOf[UserConfig], codecRegistry).toJson).extract[Map[String, Any]]
val merged = deepMerge(firstJson, secondJson)

  def deepMerge(
                 map1: Map[String, Any],
                 map2: Map[String, Any],
                 accum: MutableMap[String, Any] = MutableMap[String, Any]()
               ): MutableMap[String, Any] = {
    map1 foreach {
      case (key, value: Map[String, Any]) => {
        map2.get(key) match {
          case Some(oldValue: Map[String, Any]) => {
            accum.put(key, deepMerge(value, map2, MutableMap(oldValue.toSeq: _*) ))
          }
          case None => accum.put(key, value)
        }
      }
      case (key, value) => {
        accum.put(key, value)
      }
    }
    accum
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM