Skip to content

Instantly share code, notes, and snippets.

@claytantor
Created November 23, 2014 04:41
Show Gist options
  • Save claytantor/b64b4c9fb3177761dd1b to your computer and use it in GitHub Desktop.
Save claytantor/b64b4c9fb3177761dd1b to your computer and use it in GitHub Desktop.
DatomicClient for scala
package db
import scala.language.reflectiveCalls
import datomisca._
import scala.concurrent._
import scala.concurrent.duration.Duration
import java.util.{Date => JDate}
import datomisca.executioncontext.ExecutionContextHelper._
class DatomicClient {
/*
* Datomic URI definition
* This defines an in-memory database
* named 'datomisca-getting-started'
*/
val uri = "datomic:mem://datomisca-getting-started"
// create the database
Datomic.createDatabase(uri)
/*
* Get a connection to the database
* and make it implicit in scope
*/
implicit val conn = Datomic.connect(uri)
def connect() = {
// transact the schema, which returns a future
val fut = Datomic.transact(PersonSchema.txData) flatMap { _ =>
// Another temporary identity for a new entity for 'John'
val johnId = DId(Partition.USER)
/*
* A person entity for 'John'
* It is defined using pairs of
* attributes and values that can
* be converted to the Datomic type
* of the attribute
*/
val john = (
SchemaEntity.newBuilder
+= (PersonSchema.name -> "John")
+= (PersonSchema.age -> 31)
+= (PersonSchema.birth -> new JDate)) withId johnId
Datomic.transact(john) map { tx =>
println(s"Temporary identity for John: $johnId")
println()
println(s"Persisted identity for John: ${tx.resolve(johnId)}")
println()
val queryFindByName = Query("""
[
:find ?e ?name ?age ?birth
:in $ ?limit
:where
[?e :person/name ?name]
[?e :person/age ?age]
[?e :person/birth ?birth]
[(< ?age ?limit)]
]
""")
}
}
// await the result of the future
Await.result(fut, Duration("2 seconds"))
Datomic.shutdown(true)
// IF RUNNING FROM SBT RUNTIME :
// without this, in SBT, if you run the program 2x, it fails
// with weird cache exception linked to the way SBT manages
// execution context and classloaders...
defaultExecutorService.shutdownNow()
}
}
/**
* An object to hold the schema data for the Person entity
*/
object PersonSchema {
/**
* The namespaces used in the schema.
* We put them in an object ns for
* asthetic purposes.
*/
object ns {
val person = new Namespace("person") {
/*
* Note that we need,
* import scala.language.reflectiveCalls
* as the type of person is Namespace { val character: Namespace }
*/
val character = Namespace("person.character")
}
}
/*
* The attributes of the person entity
*/
val name = Attribute(ns.person / "name", SchemaType.string, Cardinality.one) .withDoc("The name of a person")
val age = Attribute(ns.person / "age", SchemaType.long, Cardinality.one) .withDoc("The age of a person")
val birth = Attribute(ns.person / "birth", SchemaType.instant, Cardinality.one) .withDoc("The birth date of a person")
val interests = Attribute(ns.person / "interests", SchemaType.ref, Cardinality.many).withDoc("The interests of a person")
/*
* A set of keyword identified entities.
* A standard Datomic pattern to implement
* an enumeration.
*/
val cooking = AddIdent(ns.person.character / "cooking")
val sports = AddIdent(ns.person.character / "sports")
val travel = AddIdent(ns.person.character / "travel")
val movies = AddIdent(ns.person.character / "movies")
val books = AddIdent(ns.person.character / "books")
/*
* The transaction data for the schema.
* This is simply a sequence of the
* attributes and idents
*/
val txData = Seq(
name, age, birth, interests,
cooking, sports, travel, movies, books
)
}
@claytantor
Copy link
Author

I know this works, the examples originally failed with the Jane part.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment