Skip to content

Collection columns

Flavian Alexandru edited this page May 29, 2015 · 8 revisions

Build Status Coverage Status Maven Central Download

back to top

Cassandra collections do not allow custom data types. Storing JSON as a string is possible, but it's still a text column as far as Cassandra is concerned. The type in the below example is always a default C* type.

Examples on how to use JSON columns can be found in JsonColumnTest.scala

phantom columns Cassandra columns
ListColumn.<type> list<type>
SetColumn.<type> set<type>
MapColumn.<type, type> map<type, type>
JsonColumn.<type> text
JsonListColumn.<type> list<text>
JsonSetColumn.<type> set<type>

JSON columns require you to define a toJson and fromJson method, telling phantom how to go from a String to the type you need. It makes no assumptions as to what library you are using, although we have tested with lift-json and play-json.

An example of a fully working Cassandra table using the whole variety of JSON columns can be found below.

import com.websudos.phantom.builder.query.InsertQuery
import com.websudos.phantom.dsl._
import com.websudos.phantom.testkit._
import net.liftweb.json.{DefaultFormats, Extraction, JsonParser, compactRender}

case class JsonTest(prop1: String, prop2: String)

case class JsonClass(
  id: UUID,
  name: String,
  json: JsonTest,
  jsonList: List[JsonTest],
  jsonSet: Set[JsonTest]
)


class JsonTable extends CassandraTable[JsonTable, JsonClass] {

  implicit val formats = DefaultFormats

  object id extends UUIDColumn(this) with PartitionKey[UUID]

  object name extends StringColumn(this)

  object json extends JsonColumn[JsonTable, JsonClass, JsonTest](this) {
    override def fromJson(obj: String): JsonTest = {
      JsonParser.parse(obj).extract[JsonTest]
    }

    override def toJson(obj: JsonTest): String = {
      compactRender(Extraction.decompose(obj))
    }
  }

  object jsonList extends JsonListColumn[JsonTable, JsonClass, JsonTest](this) {
    override def fromJson(obj: String): JsonTest = {
      JsonParser.parse(obj).extract[JsonTest]
    }

    override def toJson(obj: JsonTest): String = {
      compactRender(Extraction.decompose(obj))
    }
  }

  object jsonSet extends JsonSetColumn[JsonTable, JsonClass, JsonTest](this) {
    override def fromJson(obj: String): JsonTest = {
      JsonParser.parse(obj).extract[JsonTest]
    }

    override def toJson(obj: JsonTest): String = {
      compactRender(Extraction.decompose(obj))
    }
  }

  def fromRow(row: Row): JsonClass = {
    JsonClass(
      id(row),
      name(row),
      json(row),
      jsonList(row),
      jsonSet(row)
    )
  }
}

object JsonTable extends JsonTable with PhantomCassandraConnector {
  def store(sample: JsonClass): InsertQuery.Default[JsonTable, JsonClass] = {
    insert
      .value(_.id, sample.id)
      .value(_.name, sample.name)
      .value(_.json, sample.json)
      .value(_.jsonList, sample.jsonList)
      .value(_.jsonSet, sample.jsonSet)
  }
}