【问题标题】:How do I turn a Scala case class into a mongo Document如何将 Scala 案例类转换为 mongo 文档
【发布时间】:2015-11-11 02:51:05
【问题描述】:

我想构建一个通用方法来将 Scala 案例类转换为 Mongo 文档。

一个有前途的Document constructor

fromSeq(ts: Seq[(String, BsonValue)]): Document

我可以将案例类转换为 Map[String -> Any],但是我丢失了使用隐式转换到 BsonValues 所需的类型信息。也许 TypeTags 可以帮助解决这个问题?

这是我尝试过的:

import org.mongodb.scala.bson.BsonTransformer
import org.mongodb.scala.bson.collection.immutable.Document
import org.mongodb.scala.bson.BsonValue

case class Person(age: Int, name: String) 

//transform scala values into BsonValues
def transform[T](v: T)(implicit transformer: BsonTransformer[T]): BsonValue = transformer(v)

// turn any case class into a Map[String, Any]
def caseClassToMap(cc: Product) = { 
  val values = cc.productIterator
  cc.getClass.getDeclaredFields.map( _.getName -> values.next).toMap
}

// transform a Person into a Document
def personToDocument(person: Person): Document = {  
  val map = caseClassToMap(person)

  val bsonValues = map.toSeq.map { case (key, value) =>
    (key, transform(value))
  }

  Document.fromSeq(bsonValues)
}

<console>:24: error: No bson implicit transformer found for type Any. Implement or import an implicit BsonTransformer for this type.
           (key, transform(value))

【问题讨论】:

    标签: mongodb scala


    【解决方案1】:
    def personToDocument(person: Person): Document = {  
        Document("age" -> person.age, "name" -> person.name) 
    }
    

    【讨论】:

    • 这作为一个实用的解决方案很糟糕。我可以想象只有按小时计酬才能做到这一点。
    【解决方案2】:

    以下代码无需手动转换对象即可工作。

    import reactivemongo.api.bson.{BSON, BSONDocument, Macros}
    
    case class Person(name:String = "SomeName", age:Int = 20)
    
    implicit val personHandler = Macros.handler[Person]
    
    val bsonPerson = BSON.writeDocument[Person](Person())
    
    println(s"${BSONDocument.pretty(bsonPerson.getOrElse(BSONDocument.empty))}")
    

    【讨论】:

      【解决方案3】:

      您可以使用 Salat https://github.com/salat/salat。一个很好的例子可以在这里找到 - https://gist.github.com/bhameyie/8276017。这是一段可以帮助你的代码 -

      import salat._
      
      val dBObject = grater[Artist].asDBObject(artist)
      artistsCollection.save(dBObject, WriteConcern.Safe)
      

      【讨论】:

      【解决方案4】:

      我能够使用 org.bson.BsonDocumentWriter 将案例类序列化为 BsonDocument。下面的代码使用 scala 2.12 和 mongo-scala-driver_2.12 版本 2.6.0 运行

      我对这个解决方案的追求得到了这个答案的帮助(他们试图在相反的方向序列化):Serialize to object using scala mongo driver?

      import org.mongodb.scala.bson.codecs.Macros
      import org.mongodb.scala.bson.codecs.DEFAULT_CODEC_REGISTRY
      import org.bson.codecs.configuration.CodecRegistries.{fromRegistries, fromProviders}
      import org.bson.codecs.EncoderContext
      import org.bson.BsonDocumentWriter
      import org.mongodb.scala.bson.BsonDocument
      import org.bson.codecs.configuration.CodecRegistry
      import org.bson.codecs.Codec
      
      case class Animal(name : String, species: String, genus: String, weight: Int)
      
      object TempApp {
      
        def main(args: Array[String]) {
      
          val jaguar = Animal("Jenny", "Jaguar", "Panthera", 190)
      
          val codecProvider = Macros.createCodecProvider[Animal]()
          
          val codecRegistry: CodecRegistry = fromRegistries(fromProviders(codecProvider), DEFAULT_CODEC_REGISTRY)
      
          val codec = Macros.createCodec[Animal](codecRegistry)
      
          val encoderContext = EncoderContext.builder.isEncodingCollectibleDocument(true).build()
      
          var doc = BsonDocument()
      
          val writr = new BsonDocumentWriter(doc) // need to call new since Java lib w/o companion object
      
          codec.encode(writr, jaguar, encoderContext)
      
          print(doc)
      
        }
      
      };
      
      

      【讨论】:

        猜你喜欢
        • 2016-07-27
        • 2014-12-18
        • 1970-01-01
        • 2015-06-16
        • 2015-10-23
        • 1970-01-01
        • 2014-01-08
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多