Ошибки в примере класса поиска Elastic4s, если в документе результата отсутствует поле
Я работал с этим примером из руководства Elastic4s. Он работает нормально, пока не попытается получить документ, в котором нет поля, указанного в классе дела.
В этом примере из руководства, скажем, только один результат name
и пропустил location
поле. Это дало бы эту ошибку:
java.util.NoSuchElementException: ключ не найден: местоположение
Я ищу хороший подход к результатам поиска, которые имеют различные поля.
Пример кода:
case class Character(name: String, location: String)
implicit object CharacterHitAs extends HitAs[Character] {
override def as(hit: RichSearchHit): Character = {
Character(hit.sourceAsMap("name").toString, hit.sourceAsMap("location").toString) }}
val resp = client.execute {
search in "gameofthrones" / "characters" query "kings landing"
}.await
val characters :Seq[Character] = resp.as[Character]
1 ответ
При разработке case class
с необязательными параметрами, используйте Option
:
case class Character(name: String, location: Option[String])
Character("Tyrion Lannister", None)
Затем все, что вам нужно сделать, это изменить ваш экстрактор данных, чтобы передать None Option, если он не находит данные:
val tyrion = Map("location" -> "King's Landing", "name" -> "Cersei Lannister")
val cersei = Map("father" -> "Tywin Lannister?", "name" -> "Cersei Lannister")
val jaime = Map("father" -> "Tywin Lannister", "location" -> "Tower of the Hand")
val characters = List(tyrion, cersei, jaime)
case class Character(name: String, location: Option[String])
characters.map(x => Character(x.getOrElse("name", "A CHARACTER HAS NO NAME"), x.get("location")))
Результат characters.map(...)
это:
res0: List[Character] = List(
Character(Cersei Lannister,Some(King's Landing)),
Character(Cersei Lannister,None),
Character(A CHARACTER HAS NO NAME NAME,Some(Tower of the Hand)))
Из исходного кода для RichSearchHit
, sourceAsMap
должен вернуть Map
объект:
def sourceAsMap: Map[String, AnyRef] = if (java.sourceAsMap == null) Map.empty else java.sourceAsMap.asScala.toMap
Учитывая, что вы используете Map
сокращенно, вы сможете преобразовать свой код в:
case class Character(name: String, location: Option[String])
implicit object CharacterHitAs extends HitAs[Character] {
override def as(hit: RichSearchHit): Character = {
Character(hit.sourceAsMap.getOrElse("name", "A CHARACTER HAS NO NAME"), hit.sourceAsMap.get("location")) }}