我定义了以下要进行模型化的类:
<ComboBox Name="cb" Grid.IsSharedSizeScope="True" ItemsSource="{DynamicResource items}">
<ComboBox.Resources>
<!-- We'll use this dummy value to represent the header row. -->
<!-- The type and value are arbitrary; we just need a unique type -->
<!-- for DataTemplate selection to work with. -->
<system:Int32 x:Key="HeaderPlaceholder">-1</system:Int32>
<CompositeCollection x:Key="items">
<StaticResource ResourceKey="HeaderPlaceholder" />
<CollectionContainer Collection="{Binding Source={x:Reference cb},
Path=DataContext.Data}"/>
</CompositeCollection>
<!-- DataTemplate for the header item -->
<DataTemplate DataType="{x:Type system:Int32}">
<DataTemplate.Resources>
<!-- Make the TextBlocks black even though they are disabled -->
<Style TargetType="TextBlock">
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Foreground" Value="Black" />
</Trigger>
</Style.Triggers>
</Style>
</DataTemplate.Resources>
<StackPanel>
<Grid TextElement.FontWeight="Bold">
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="A"/>
<ColumnDefinition Width="5"/>
<ColumnDefinition SharedSizeGroup="B"/>
</Grid.ColumnDefinitions>
<Grid.Children>
<TextBlock Grid.Column="0" Text="Name"/>
<TextBlock Grid.Column="2" Text="Occupation"/>
</Grid.Children>
</Grid>
<Separator />
</StackPanel>
</DataTemplate>
<!-- DataTemplate for a normal, selectable item -->
<DataTemplate DataType="{x:Type obj:Employee}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="A"/>
<ColumnDefinition Width="5"/>
<ColumnDefinition SharedSizeGroup="B"/>
</Grid.ColumnDefinitions>
<Grid.Children>
<TextBlock Grid.Column="0" Text="{Binding Name}"/>
<TextBlock Grid.Column="2" Text="{Binding Occupation}"/>
</Grid.Children>
</Grid>
</DataTemplate>
</ComboBox.Resources>
<ComboBox.ItemContainerStyle>
<!-- Make sure the header item is disabled so it can't be selected -->
<Style TargetType="ComboBoxItem">
<Style.Triggers>
<Trigger Property="DataContext" Value="{StaticResource HeaderPlaceholder}">
<Setter Property="IsEnabled" Value="False" />
</Trigger>
</Style.Triggers>
</Style>
</ComboBox.ItemContainerStyle>
</ComboBox>
现在,我想从这样的反应性mongo中获取这种类型的一个对象(在另一个类中):
case class Record(
recordKey: String,
channels: Map[String, Channel],
)
object Record {
implicit val RecordFormat = Json.format[Record]
}
但是这段代码没有编译:
import scala.concurrent.duration._
import scala.concurrent.{Future, Await}
import scala.concurrent.ExecutionContext.Implicits.global
import reactivemongo.api._
import reactivemongo.api.collections.bson.BSONCollection
import reactivemongo.bson.BSONDocument
object Test {
val collection = connect()
val timeout = 10.seconds
def connect() : BSONCollection = {
val config = ConfigFactory.load()
val driver = new MongoDriver
val connection = driver.connection(List(config.getString("mongodb.uri")))
val db = connection("/toto")
db.collection("foo")
}
def findRecord(recordKey : String) : Record = {
return Test.collection
.find(BSONDocument("recordKey"->recordKey))
.one[Record]
}
我也测试过:
could not find implicit value for parameter reader: reactivemongo.bson.BSONDocumentReader[Record]
我还添加了def findRecord(recordKey : String) : Record = {
val futureRecord : Future[Option[Record]] =
Test.collection
.find(BSONDocument("recordKey"->recordKey))
.one[Record]
return Await.result(futureRecord, 10.seconds).getOrElse(null)
}
:
build.sbt
请注意,它不是libraryDependencies ++= Seq(
"org.apache.spark" % "spark-streaming_2.10" % "1.5.2",
"org.apache.spark" % "spark-streaming-kafka_2.10" % "1.5.2",
"org.slf4j" % "slf4j-api" % "1.7.13",
"org.slf4j" % "slf4j-simple" % "1.7.13",
"com.amazonaws" % "aws-java-sdk" % "1.10.12",
"com.typesafe.play" % "play-json_2.10" % "2.4.6",
"com.typesafe" % "config" % "1.3.0",
"org.scalaj" %% "scalaj-http" % "2.2.1",
"com.typesafe.akka" % "akka-actor_2.10" % "2.3.14",
"org.reactivemongo" %% "reactivemongo" % "0.11.9",
"com.github.nscala-time" %% "nscala-time" % "2.6.0"
)
。
答案 0 :(得分:2)
您需要为案例类BSONDocumentReader
定义Record
。这是Documentation的链接。非常类似于Play JSON读者和写作者Reactive Mongo需要了解如何在域对象和BSONDocument
之间来回转换。与Play JSON类似,您可以以更手动的方式编写这些内容(编写BSONDocumentReader
实例和BSONDocumentWriter
实例)并自定义每个细节并应用转换等。类似于播放JSON和#的样式39;您在上面使用的format
ReactiveMongo确实提供了有用的宏来为您生成这些类。
对于您的Record类,您需要向对象添加这样的隐式val:
import reactivemongo.bson._
implicit val recordHandler: BSONHandler[BSONDocument, Record] = Macros.handler[Record]
/* Or only one of these [if your only ever writing or reading this data etc:
implicit val recordReader: BSONDocumentReader[Record] = Macros.reader[Record]
implicit val recordWriter: BSONDocumentWriter[Record] = Macros.writer[Record]
*/
我想说尝试从宏开始,看看它们是否满足您的需求。如果您需要更多控制处理/转换,可以定义自己的BSONDocumentReader
和BSONDocumentWriter
实例。
更新了记录类
import play.api.libs.json.Json
import reactivemongo.bson._
case class Channel(label: String,amplitude: Double,position: Option[String])
object Channel {
implicit val ChannelFormat = Json.format[Channel]
implicit val channelHandler: BSONHandler[BSONDocument, Channel] = Macros.handler[Channel]
}
object RecordType extends Enumeration {
type RecordType = Value
val T1 = Value
implicit val enumFormat = new Format[RecordType] {
def reads(json: JsValue) = JsSuccess(RecordType.withName(json.as[String]))
def writes(enum: RecordType) = JsString(enum.toString)
}
implicit object RecordTypeReader extends BSONDocumentReader[RecordType] {
def read(doc: BSONDocument) : RecordType = {
RecordType.withName(doc.getAs[String]("recordType").get)
}
}
implicit object RecordTypeWriter extends BSONDocumentWriter[RecordType] {
def write(recordType: RecordType) : BSONDocument = BSONDocument(
"recordType" -> BSONString(recordType.toString)
)
}
}
case class Record(recordKey: String,recordType: RecordType.Value,channels: Map[String, Channel])
object Record {
implicit val RecordFormat = Json.format[Record]
implicit val recordHandler: BSONHandler[BSONDocument, Record] = Macros.handler[Record]
}