关于ReactiveMongo的误解错误

时间:2016-02-05 15:43:42

标签: mongodb scala reactivemongo

我定义了以下要进行模型化的类:

<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" )

1 个答案:

答案 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]
*/

我想说尝试从宏开始,看看它们是否满足您的需求。如果您需要更多控制处理/转换,可以定义自己的BSONDocumentReaderBSONDocumentWriter实例。

更新了记录类

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]
}