-
Notifications
You must be signed in to change notification settings - Fork 186
Automated schema generation
Keyspace level generation and setting properties for keyspaces is provided separately and we are in the process of porting that to the main DSL, but CQL 3 Table schemas are automatically generated from the Scala code. To create a schema in Cassandra from a table definition:
import scala.concurrent.Await
import scala.concurrent.duration._
import com.websudos.phantom.dsl._
Await.result(ExampleRecord.create().future(), 5000 millis)
Of course, you don't have to block unless you want to. Phantom is capable of handling more advanced scenarios as well, including and not limited to things like creating secondary indexes and initialising them in due time and so on.
Secondary indexes are a non scalable flavour of Cassandra indexing that allows us to query certain columns without needing to duplicate data. They do not scale very well at well, but they remain useful for tables where the predicted cardinality for such records is very small.
That aside, it's worth noting phantom is capable of auto-generating your CQL schema and initialising all your indexes automatically, and this functionality is exposed through the exact same table.create.future()
.
sealed class IndexedCollectionsTable extends CassandraTable[ConcreteIndexedCollectionsTable, TestRow] {
object key extends StringColumn(this) with PartitionKey[String]
object list extends ListColumn[String](this)
object setText extends SetColumn[String](this) with Index[Set[String]]
object mapTextToText extends MapColumn[String, String](this) with Index[Map[String, String]]
object setInt extends SetColumn[Int](this)
object mapIntToText extends MapColumn[Int, String](this) with Index[Map[Int, String]] with Keys
object mapIntToInt extends MapColumn[Int, Int](this) with Index[Map[Int, Int]] with Entries
def fromRow(r: Row): TestRow = {
TestRow(
key = key(r),
list = list(r),
setText = setText(r),
mapTextToText = mapTextToText(r),
setInt = setInt(r),
mapIntToText = mapIntToText(r),
mapIntToInt = mapIntToInt(r)
)
}
}
Using Database
objects and injecting them into your controllers and other parts where they need to exist is not something that we have designed just for application layering purposes. It is indeed a very powerful feature that you can perfectly encapsulate the scope where a session
exists using a Database
object, but another very powerful feature is the ability to auto-generate and sync the schema for entire databases with a single method.
Let's have a look at this example taken from the dsl module inside phantom. We use this for testing purposes, and all phantom tests are written to run against this database, which is then injected into all the test suites using a provider trait, namely DatabaseProvider
.
To initialise the entire database in a single call, you can use a single call to the autocreate().future()
method. If you are using the Twitter API provided via the phantom-finagle
module, you can also call autocreate.execute()
and get a Twitter future back, provided you have imported the right implicits.
Await.result(database.autocreate.future(), 10.seconds)
class TestDatabase(override val connector: KeySpaceDef) extends DatabaseImpl(connector) {
object articles extends ConcreteArticles with connector.Connector
object articlesByAuthor extends ConcreteArticlesByAuthor with connector.Connector
object basicTable extends ConcreteBasicTable with connector.Connector
object enumTable extends ConcreteEnumTable with connector.Connector
object namedEnumTable extends ConcreteNamedEnumTable with connector.Connector
object clusteringTable extends ConcreteClusteringTable with connector.Connector
object complexClusteringTable extends ConcreteComplexClusteringTable with connector.Connector
object brokenClusteringTable extends ConcreteBrokenClusteringTable with connector.Connector
// ..
}
In some instances you may want to override the default query used to create a table, and that could be for the purpose of specifying more advanced options at query creation time.
The default query used by phantom during auto-generation is: database.myTable.create.ifNotExists()
Which will produce the following CQL equivalent: CREATE TABLE IF NOT EXISTS mytable
, with no options specified.
To stay up-to-date with our latest releases and news, follow us on Twitter: @outworkers.
- Issues and questions
- Adopters
- Roadmap
- Changelog
- Tutorials
- Commercial support
- Using phantom in your project
- Primitive columns
- Optional primitive columns
- Collection columns
- Collection operators
- Automated schema generation
- Indexing columns
- Data modeling with phantom
- Querying with phantom
- Asynchronous iterators
- Batch statements
- Apache Thrift integration
- Apache ZooKeeper integration
- The phantom testkit