macros
Nesta página
Visão geral
O driver Scala permite usar classes de caso para representar documentos em uma coleção usando o auxiliar Macros
. Classes de caso simples e classes de caso aninhadas são suportadas. A modelagem hierárquica pode ser obtida usando uma traça ou classe selada e, em seguida, fazendo com que as classes de caso implementem a traça principal.
Muitos tipos simples de Scala são suportados e podem ser ordenados em seu tipo BsonValue
correspondente. A lista a seguir descreve os tipos Scala e sua representação BSON segura por tipo:
Tipo Scala | Tipo de JSON |
---|---|
classe de caso | Documento |
Iterable | Array |
Date | Data |
Boolean | Boolean |
Double | Double |
Int | Int32 |
Long | Int64 |
String | String |
Array[Byte] | Binário |
None | Zero |
Criando codecs
Para criar um codec para sua classe de caso, use os métodos do auxiliar de objeto Macros
. Você deve usar o método Macros.createCodecProvider()
para criar um CodecProvider
. Um CodecProvider
passa o CodecRegistry
configurado para o Codec
subjacente e fornece acesso a todos os codecs configurados.
Para criar um CodecProvider
, defina o tipo de classe case ao chamar createCodecProvider()
, conforme mostrado no código a seguir:
import org.mongodb.scala.bson.codecs.Macros case class Person(firstName: String, secondName: String) val personCodecProvider = Macros.createCodecProvider[Person]()
O personCodecProvider
pode então ser utilizado quando convertido em um CodecRegistry
utilizando os auxiliares estáticos do CodecRegistries
. O seguinte código cria um novo registro de codec, combinando o novo personCodecProvider
e o registro de codec padrão:
import org.mongodb.scala.bson.codecs.DEFAULT_CODEC_REGISTRY import org.bson.codecs.configuration.CodecRegistries.{fromRegistries, fromProviders} val codecRegistry = fromRegistries( fromProviders(personCodecProvider), DEFAULT_CODEC_REGISTRY )
O assistente Macros
também tem um método createCodecProvider()
implícito que pega o Class[T]
e cria um CodecProvider
a partir disso. Este método é mais conciso, especialmente ao definir vários provedores:
import org.mongodb.scala.bson.codecs.Macros._ import org.mongodb.scala.bson.codecs.DEFAULT_CODEC_REGISTRY import org.bson.codecs.configuration.CodecRegistries.{fromRegistries, fromProviders} case class Address(firstLine: String, secondLine: String, thirdLine: String, town: String, zipCode: String) case class ClubMember(person: Person, address: Address, paid: Boolean) val codecRegistry = fromRegistries( fromProviders(classOf[ClubMember], classOf[Person], classOf[Address]), DEFAULT_CODEC_REGISTRY )
Classes seladas e ADTs
As estruturas de classe hierárquica são suportadas por meio de características e classes seladas. Cada subclasse é tratada especificamente pelo codec gerado, portanto, você só precisa criar um CodecProvider
para a propriedade ou classe principal selada. Internamente, um campo extra (_t
) é armazenado junto com os dados para que a subclasse correta possa ser filtrada ao decodificar os dados. O código a seguir é um exemplo de uma estrutura semelhante a uma árvore contendo nós de ramificação e folha:
sealed class Tree case class Branch(b1: Tree, b2: Tree, value: Int) extends Tree case class Leaf(value: Int) extends Tree val codecRegistry = fromRegistries( fromProviders(classOf[Tree]), DEFAULT_CODEC_REGISTRY )
Opções e valores de nenhum
Por padrão, os valores Option
são sempre armazenados. No driver v2.1.0, novos auxiliares foram adicionados para que os valores None
não fossem armazenados no banco de dados. No exemplo a seguir, o driver só armazena um endereço se houver:
import org.mongodb.scala.bson.codecs.Macros case class Person(firstName: String, secondName: String, address: Option[Address]) val personCodecProvider = Macros.createCodecProviderIgnoreNone[Person]()
Nomes de campo alternativos
A anotação BsonProperty
pode ser utilizada para configurar a chave de campo BSON a ser utilizada para uma determinada propriedade. O exemplo seguinte utiliza a anotação BsonProperty
para alterar como o campo firstName
é armazenado:
case class Person(@BsonProperty("first_name") firstName: String, secondName: String)