MongoDB Scala 驱动程序。如何仅更新 case class 对象中已更改文档的字段
MongoDB Scala driver. How to update only changed document's fields from the case class object
我有以下情况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]))
}
}
并尝试以这种方式更新已存储的文档:
def update(userConfig: UserConfig) = {
collection.updateOne(equal("userId", 1), userConfig).headOption()
}
但是当我尝试这样做时出现以下错误:
Invalid BSON field name userId
我也试过使用 replaceOne 方法,但它会替换整个对象并删除我不想删除的字段。
我想要达到的目标:
我只想在 mongodb 文档中保存更改的字段。这些字段由 graphql request
给出
现在,我找到了一种方法来转换和递归合并新对象与旧对象,就像这样。如果有人有更好的代码或意见 - 我会很乐意聊天
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
}
}
我有以下情况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]))
}
}
并尝试以这种方式更新已存储的文档:
def update(userConfig: UserConfig) = {
collection.updateOne(equal("userId", 1), userConfig).headOption()
}
但是当我尝试这样做时出现以下错误:
Invalid BSON field name userId
我也试过使用 replaceOne 方法,但它会替换整个对象并删除我不想删除的字段。
我想要达到的目标: 我只想在 mongodb 文档中保存更改的字段。这些字段由 graphql request
给出现在,我找到了一种方法来转换和递归合并新对象与旧对象,就像这样。如果有人有更好的代码或意见 - 我会很乐意聊天
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
}
}