# Kotlin NoSQL Kotlin NoSQL is a reactive and type-safe DSL for working with NoSQL databases. ## Status Under development (POC). The following NoSQL databases are supported now: - [MongoDB](https://www.mongodb.org/) Feedback is welcome. ## Download To use it with Maven insert the following code in your pom.xml file: ```xml org.jetbrains.kotlin kotlin-nosql-mongodb 0.1-SNAPSHOT kotlin-nosql http://repository.jetbrains.com/kotlin-nosql ``` To use it with Gradle insert the following code in your build.gradle: ```groovy repositories { maven { url "http://repository.jetbrains.com/kotlin-nosql" } } dependencies { compile 'org.jetbrains.kotlin:kotlin-nosql-mongodb:0.1-SNAPSHOT' } ``` ## Getting Started Demo: http://www.youtube.com/watch?v=80xgl3KThvM ### Basics #### Define a schema ```kotlin object Comments: DocumentSchema("comments", Comment::class) { val discussionId = id("discussion_id", Discussions) val slug = string("slug") val fullSlug = string("full_slug") val posted = dateTime("posted") val text = string("text") val AuthorInfo = AuthorInfoColumn() class AuthorInfoColumn() : Column("author", AuthorInfo::class) { val authorId = id("id", Authors) val name = string("name") } } class Comment(val discussionId: Id, val slug: String, val fullSlug: String, posted: DateTime, text: String, authorInfo: AuthorInfo) { val id: Id? = null } class AuthorInfo(val authorId: Id, val name: String) ``` #### Define a database ```kotlin val db = MongoDB(database = "test", schemas = arrayOf(Comments), action = CreateDrop(onCreate = { // ... })) db.withSession { // ... } ``` #### Insert a document ```kotlin Comments.insert(Comment(DiscussionId, slug, fullSlug, posted, text, AuthorInfo(author.id, author.name))) ``` #### Get a document by id ```kotlin val comment = Comments.find { id.equal(commentId) }.single() ``` #### Get a list of documents by a filter expression ```kotlin val comments = Comments.find { authorInfo.id.equal(authorId) }.sortBy { posted }.skip(10).take(5).toList() ``` #### Get selected fields by document id ```kotlin val authorInfo = Comments.find { id.equal(commentId) }.projection { authorInfo }.single() ``` #### Get selected fields by a filter expression ```kotlin Comments.find { discussionId.equal(id) }).projection { slug + fullSlug + posted + text + authorInfo }.forEach { val (slug, fullSlug, posted, text, authorInfo) = it } ``` #### Update selected fields by document id ```kotlin Comments.find { id.equal(commentId) }.projection { posted }.update(newDate) ``` ```kotlin Comments.find { id.equal(commentId) }.projection { posted + text }.update(newDate, newText) ``` ### Inheritance #### Define a base schema ```kotlin open class ProductSchema(javaClass: Class, discriminator: String) : DocumentSchema("products", discriminator = Discriminator(string("type"), discriminator)) { val sku = string("sku") val title = string("title") val description = string("description") val asin = string("asin") val Shipping = ShippingColumn() val Pricing = PricingColumn() inner class ShippingColumn>() : Column("shipping", Shipping::class) { val weight = integer("weight") val dimensions = DimensionsColumn() } inner class DimensionsColumn>() : Column("dimensions", Dimensions::class) { val width = integer("width") val height = integer("height") val depth = integer("depth") } inner class PricingColumn>() : Column("pricing", Pricing::class) { val list = integer("list") val retail = integer("retail") val savings = integer("savings") val ptcSavings = integer("pct_savings") } } object Products : ProductSchema(Product::class, "") abstract class Product(val id: Id? = null, val sku: String, val title: String, val description: String, val asin: String, val shipping: Shipping, val pricing: Pricing) { val id: Id? = null } class Shipping(val weight: Int, val dimensions: Dimensions) class Dimensions(val width: Int, val height: Int, val depth: Int) class Pricing(val list: Int, val retail: Int, val savings: Int, val pctSavings: Int) ``` #### Define an inherited schema ```kotlin object Albums : ProductSchema(Album::class, discriminator = "Audio Album") { val details = DetailsColumn() class DetailsColumn() : Column("details", Details::class) { val title = string("title") val artistId = id("artistId", Artists) val genre = setOfString("genre") val tracks = TracksColumn() } class TracksColumn() : ListColumn("tracks", Track::class) { val title = string("title") val duration = integer("duration") } } class Album(sku: String, title: String, description: String, asin: String, shipping: Shipping, pricing: Pricing, val details: Details) : Product(sku, title, description, asin, shipping, pricing) class Details(val title: String, val artistId: Id, val genre: Set, val tracks: List) ``` #### Insert a document ```kotlin val productId = Products.insert(Album(sku = "00e8da9b", title = "A Love Supreme", description = "by John Coltrane", asin = "B0000A118M", shipping = Shipping(weight = 6, dimensions = Dimensions(10, 10, 1)), pricing = Pricing(list = 1200, retail = 1100, savings = 100, pctSavings = 8), details = Details(title = "A Love Supreme [Original Recording Reissued]", artistId = artistId, genre = setOf("Jazz", "General"), tracks = listOf(Track("A Love Supreme Part I: Acknowledgement", 100), Track("A Love Supreme Part II: Resolution", 200), Track("A Love Supreme, Part III: Pursuance", 300))))) } ``` #### Access documents via an abstract schema ```kotlin for (product in Products.find { id.equal(productId) }) { if (product is Album) { } } ``` #### Access documents via an inherited schema ```kotlin val album = Albums.find { details.artistId.equal(artistId) }.single() ``` ## Examples - [PetClinic Sample Application](http://kotlin-nosql-mongodb-petclinic.herokuapp.com) ([GitHub](https://github.com/cheptsov/kotlin-nosql-mongodb-petclinic))