Java: Object Type Mappings in Elasticsearch

Verschachtelte Strukturen in Elasticsearch zu mappen, ist strukturell gesehen eigentlich gut dokumentiert, siehe Object Type (Achtung: Nicht zu verwechseln mit Nested Type!). In Java kann dabei trotzdem einiges schiefgehen – zumindest in v0.90.x, über die aktuellen Versionen kann ich nichts sagen.

Zuerst ein Klassiker, wenn man sich die zahlreichen Tipps dazu im Internet ansieht:

Merge failed with failures {[mapper [field.innerField] has different index values, mapper [field.innerField] has different tokenize values, mapper [field.innerField] has different index_analyzer]}

Das liegt gerne mal daran, dass der Index vor dem Mapping aufgebaut wurde. Was aber nicht bedeutet, dass man das selber explizit so macht! Es kann ganz simpel daran liegen, dass die früher erzeugten (und jetzt veralteten) Dateien auf der Platte nicht mehr passen. Alle Dateien löschen und neu erzeugen lassen, dann kann der Fehler schon verschwunden sein m(

Dann, auch sehr verwirrend: Der XContentBuilder hat eine string()-Funktion (nicht zu verwechseln mit toString()). Die hilft beim Debuggen insofern, als dass man das erzeugte Mapping/JSON ausgeben kann. Allerdings “tut” string() intern irgendwas, keine Ahnung, den Stream schließen oder so. Mit einem string() im Code bekommt man eine NullPointerException in UTF8JsonGenerator.writeRaw(UTF8JsonGenerator.java:670). Tollerweise (trollerweise?) liegt die Klasse zwar unter org.elasticsearch.common.jackson.core.json.UTF8JsonGenerator, die Sourcen sind aber nicht Teil der ES-Sourcen… und der UTF8JsonGenerator hat sehr viele writeRaw()-Methoden.

Bis man darauf kommt, dass es ausschließlich an string() liegt, kann schon mal einige Zeit vergehen: Mit einem string() im Code kann man zwar das erzeugte JSON ausgeben, dieses ist aber völlig irrelevant. Es kann sogar ungültig sein, etwa durch ein überzähliges endObject() – durch string() sieht man statt des eigentlichen

 JsonGenerationException: Current context not an object but ROOT

nur den NullPointer von oben.

Trotzdem ist string() nötig, denn drölf verschachtelte endObject() und field() werden schnell unübersichtlich. Meine Empfehlung: Das JSON unter Einsatz von string() gemäß der Doku aufbauen, string() dann auskommentieren, und erst dann die auftretenden Fehlermeldungen lesen.

Play: Lokales .jar als Dependency

bsplw:

via

PS: Die referenzierte .jar ist dieses feine Plugin für Elasticsearch, das es natürlich auch im Maven Repo gibt.