2016-08-18 1 views
1

Я работаю с этим примером из руководства Elastic4s. Он работает нормально, пока не попытается извлечь документ, который не имеет поля, указанного в классе case.Elastic4s поиск случай класс пример ошибки, когда в документе результата отсутствует поле

В этом примере из руководства, скажем, один результат имел только name и отсутствовал поле location. Это приведет к такой ошибке:

java.util.NoSuchElementException: key not found: location

Я ищу подходящий подход, чтобы иметь дело с результатами поиска, которые имеют разные поля.

Пример кода:

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] 

ответ

0

При разработке case class с дополнительными параметрами, используйте Option:

case class Character(name: String, location: Option[String]) 

Character("Tyrion Lannister", None) 

Тогда все, что вам нужно сделать, это изменить свой экстрактор данных передать параметр Нет, если он не находит данные:

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")) }} 
+0

Я полностью согласен, что класс Option - это путь. Я рассматривал этот вопрос больше и проблема, и я считаю, что проблема заключается в исходной части ASMap и toString неявного объекта. hit.sourceAsMap ("location"). toString Объявление функции sourceAsMap передает данные из указанного поля в ответе Elasticsearch. Однако, когда результат Map.empty, я думаю, что метод toString является ошибкой. –

+0

Обновление: я удалил toString и изменил ссылки в классе case на AnyRef. Я все еще получаю ключ, который не найден. Поэтому я вернулся, чтобы врываться в библиотеку для ответов. –

+0

@JimHendricks Создает ли 'sourceAsMap()' объект Scala 'Map'? Если это так, и я думаю, что это так, вы можете называть 'get' на нем, который должен возвращать' None', если нет ключа: 'hit.sourceAsMap.get (" location "))' –

 Смежные вопросы

  • Нет связанных вопросов^_^