Reputation: 795
I have a class which I want to begin indexing into ElasticSearch using the Scala client elastic4s. I have extended DocumentMap to allow me to insert the documents. The simple values like String, Int etc are working but I cannot seem to get a List of another class to map correctly.
The documents look similar to this:
case class AThing(UserName: String, Comment: String, Time: String)
extends DocumentMap {
override def map: Map[String, Any] = Map(
"UserName" -> UserName,
"Comment" -> Comment,
"Time" -> Time
)
}
case class ThingsThatHappened(Id: String, Things: Seq[AThing] = Nil)
extends DocumentMap {
override def map: Map[String, Any] = Map(
"Id" -> Id,
"Things" -> Things
)
}
It will map the Id field fine within elasticsearch but then I get a an incorrect value which looks similar to this, when the document is inserted into elasticsearch:
List(AThing(id_for_the_thing,user_name_a,typed_in_comment,2015-03-12))
Obviously this is wrong and I am expecting something a kin to this JSON structure once it has been inserted into elasticsearch, such as:
"events" : [
{
"UserName" :"user_name_a",
"Comment": "typed_in_comment",
"Time": "2015-03-12"
}
]
Does anyone know a way to map an array of complex types when indexing data using elastic4s?
Upvotes: 0
Views: 969
Reputation: 16387
Elastic4s or the java client (currently) isn't smart enough to figure out that you have a nested sequence or array, but it would work if it was a nested java map (still a bit rubbish from the Scala point of view).
I think the best thing to do is use the new Indexable typeclass that was added in 1.4.13
So, given
case class AThing(UserName: String, Comment: String, Time: String)
Then create a type class and bring it into scope
implicit object AThingIndexable extends Indexable[AThing] {
def json = ... create json here using Jackson or similar which will handle nested sequences properly
}
Then you should be able to do:
client.execute { index into "myIndex/AThings" source aThing }
It's not quite as automatic as using the DocumentMap but gives you more control.
See a unit test here with it in action
Upvotes: 1
Reputation:
First of all you need to create index in elastic4s. I assume you did this.
client.execute {
create index "myIndex" mappings (
"AThings" as(
"UserName" typed StringType,
"Comemnt" typed StringType,
"Time" typed StringType,
)
)
}
if you create this index, then you can put case class into this directly.
val aThings = AThings("username","comment","time")
client.execute {index into "myIndex/AThings" doc aThings}
Upvotes: 0