2016-08-18 2 views
1

Ich habe mit diesem Beispiel aus dem Elastic4s-Handbuch gearbeitet. Es funktioniert einwandfrei, bis es versucht, ein Dokument abzurufen, für das in der Fallklasse kein Feld angegeben ist.Elastic4s Fallklassen-Beispielfehler suchen, wenn Ergebnisdokument ein Feld fehlt

In diesem Beispiel aus dem Handbuch, sagen wir, ein Ergebnis hatte nur name und fehlte das Feld location. Es würde diesen Fehler ergeben:

java.util.NoSuchElementException: key not found: location

Ich bin auf der Suche nach einem guten Ansatz, um mit Suchergebnissen umzugehen, die unterschiedliche Felder haben.

Codebeispiel:

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] 

Antwort

0

Wenn eine case class mit optionalen Parametern zu entwickeln, verwenden Option:

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

Character("Tyrion Lannister", None) 

Dann alles, was Sie tun müssen, ist Ihre Datenextrahierers ändern, um eine Option Keine, wenn es passieren findet die Daten nicht:

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

Das Ergebnis dies von characters.map(...) ist:

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

Aus dem Quellcode für RichSearchHit, sourceAsMap ein Map Objekt zurückgeben sollte:

def sourceAsMap: Map[String, AnyRef] = if (java.sourceAsMap == null) Map.empty else java.sourceAsMap.asScala.toMap 

Vorausgesetzt, dass Sie eine Map Stenografie verwenden, sollten Sie in der Lage zu konvertieren Sie Ihre Code zu:

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

Ich stimme völlig zu, die Option-Klasse ist der Weg zu gehen. Ich habe dieses Problem mehr und das Problem untersucht, und ich glaube, dass das Problem in der SourceAsMap und dem toString Teil des impliziten Objekts ist. hit.sourceAsMap ("location"). toString Die Deklaration der sourceAsMap-Funktion ruft die Daten aus dem angegebenen Feld in der Elasticsearch-Antwort ab. Wenn das Ergebnis jedoch Map.empty ist, denke ich, dass die toString-Methode fehlerhaft ist. –

+0

Update: Ich habe den toString entfernt und die Referenzen in der Fall-Klasse zu AnyRef geändert. Ich bekomme immer noch den Schlüssel nicht gefunden Fehler. Also bin ich zurück, um in die Bibliothek nach Antworten zu graben. –

+0

@JimHendricks Sendet 'sourceAsMap()' kein Scala 'Map' Objekt zurück? Wenn es das tut - und ich denke schon - können Sie 'get' darauf aufrufen, was' None' zurückgeben sollte, wenn es keinen Schlüssel gibt: 'hit.sourceAsMap.get (" location "))' –

Verwandte Themen