将一个具有特定结构的 Scala 案例 class 映射到另一个具有不同结构的案例

Map one Scala case class with a certain structure to another with a different structure

我正在构建一个使用 Elastic4s.

Elasticsearch 对话的 Scala API

我从 Elastic4s 收到的一个响应是 SearchHit 类型并具有以下结构:

SearchHit(id: String,
          index: String,
          `type`: String,
          score: Float,
          private val _source: Map(name: String,
                                   code: String,
                                   location: Map(lat: Double, lon:Double)
                                  )
          )

我需要将此对象映射到结构的另一个对象:

case class Location(id: Option[String] = None, location: GeoLocation, code: String, name: String)

其中 GeoLocation 是:

case class GeoLocation(lat: Double, lon: Double)

如您所见,我需要映射到 Location 的大部分字段都在 _source 映射中,但我还需要映射 id

Elastic4s 提供了一个有用的类型类。它被称为 HitReader(尽管它可能会在版本 6 中更改名称 - 待发布),如果您为您的类型实现此 Location 然后您可以在搜索结果中调用 .to[T]

object LocationHitReader extends HitReader {
  def read(hit: Hit): Either[Throwable, T] = ...
}

手动实现这个不会让你比现在更进一步,但 elastic4s 然后提供使用常见 json 后端的实现 - Jackson,Json4s,Circe,喷-Json让你什么都不用做。

例如,如果您使用 Jackson,则将 elastic4s-jackson 添加到您的类路径,然后在搜索结果上方添加以下导入。

import ElasticJackson.Implicits._

然后,在您的搜索结果中,您可以调用 .to[Location] 获得 Seq[Location].safeTo[Location] 获得 Seq[Either[T, Location]

要同时获取 id,您可以创建一个自定义 HitReader,委托给库创建一个,添加 id。