如何将Scala案例类转换为mongo文档

时间:2015-11-11 02:51:05

标签: mongodb scala

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

有希望的Document constructor

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

我可以将案例类转换为Map [String - >任何],但后来我丢失了我需要使用隐式转换到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))

4 个答案:

答案 0 :(得分:3)

def personToDocument(person: Person): Document = {  
    Document("age" -> person.age, "name" -> person.name) 
}

答案 1 :(得分:0)

我能够使用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)

  }

};

答案 2 :(得分:0)

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

/var/www/html/thinopticsnewdesign/app/code/Mageplaza/LayeredNavigation/Model/Resource/Model/Fulltext/Collection.php

答案 3 :(得分:-1)

您可以使用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)