M. Karassev
M. Karassev

Reputation: 79

Cannot generate indexable for a type containing a Map with a custom Key type

I'm using scala 2.11.11, elastic4s 5.4.5 and elastic4s-circe 5.4.5

import com.sksamuel.elastic4s.ElasticDsl._
import com.sksamuel.elastic4s.TcpClient
import com.sksamuel.elastic4s.circe._
import io.circe.generic.auto._

object Test {

  val client: TcpClient = ???

  case class Something(a: Map[AnotherThing, Int])
  case class AnotherThing(b: Int)

  val smth = Something(Map.empty)

  client.execute {
    indexInto("index" / "type").doc(smth)
  }

}

This would not compile:

could not find implicit value for evidence parameter of type com.sksamuel.elastic4s.Indexable[net.lizeo.bd4m.storage.Test.Something]
indexInto("index" / "type").doc(smth)

According to the documentation:

Simply add the import for your chosen library below and then with those implicits in scope, you can now pass any type you like to doc and an Indexable will be derived automatically.

With import io.circe.generic.auto._and import com.sksamuel.elastic4s.circe._ for elastic4s-circe.

What am I missing?

Upvotes: 0

Views: 318

Answers (2)

Andrei Micu
Andrei Micu

Reputation: 3249

I haven't used Circe, but I used SprayJson and maybe my answer helps future persons looking at this question:

For Spray, I first naively thought the import com.sksamuel.elastic4s.sprayjson._ will suffice, but Spray requires a JsonProtocol for the custom case classes, like this:

object MyJsonProtocol extends DefaultJsonProtocol {
  implicit val smthFormat = jsonFormat1(Something)
  implicit val anotherThgFormat = jsonFormat1(AnotherThing)
}

And then you import both at the top of your code:

import MyJsonProtocol._
import com.sksamuel.elastic4s.sprayjson._

I think this part of auto-magic is implemented in Circe's import io.circe.generic.auto._, but maybe it doesn't work with elastic4s and you have to write it by hand.

Upvotes: 0

Ramesh Maharjan
Ramesh Maharjan

Reputation: 41957

You need to define the case classes outside the scope of Test object i.e. outside the Test class. You can define them as separate classes as well.

So correct way should be

import com.sksamuel.elastic4s.ElasticDsl._
import com.sksamuel.elastic4s.TcpClient
import com.sksamuel.elastic4s.circe._
import io.circe.generic.auto._

object Test {

  val client: TcpClient = ???

  val smth = Something(Map.empty)

  client.execute {
    indexInto("index" / "type").doc(smth)
  }

}

case class Something(a: Map[AnotherThing, Int])
case class AnotherThing(b: Int)

Upvotes: 0

Related Questions