MultiMap - Tables in SwayDB
Tags: database, scala, java, kotlin
Published: 2020-07-30 04:50:13

`MultiMap` is an extension of `Map` data type which allows storing multiple `Map`s within a single [SwayDB](https://github.com/simerplaha/SwayDB) instance. It mimics SQL's `Table` which can be used to seggregate data.

`MultiMap` is just a thin layer that uses custom types and [KeyOrdering](https://swaydb.simer.au/ordering-data/?language=scala/) to manage data segregation. 

The following code snippets demo few core functionality of `MultiMap` like nesting, expiration, streaming, transactions, replace & remove. 

## Initialise `MultiMap`
```scala
import swaydb._ //import SwayDB's API
import swaydb.serializers.Default._ //import default serialisers

//initialise an in-memory multiMap  
val map = memory.MultiMap_EAP[String, Long, String, Nothing, Bag.Less]()

//or initialise an persistent multiMap 
val pMap = persistent.MultiMap_EAP[String, Long, String, Nothing, Bag.Less]("myDir")
```
- `String` - The type of **Map ID**. In SQL this would be **Table Name**.
- `Long` - The type of **Key** for key-values stored in this Map. In SQL this would be **primary key**.
- `String` - The type of **Value** for key-values stored in the Map. In SQL this would be the **Table row**.
- `Nothing` - The function type. Using `Nothing` disables functions. Instead of a query language, SwayDB allows complex data modifications by submitting pure JVM functions. In SQL these would be `CREATE`, `INSERT` & `UPDATE` queries. You can read more about this [here](https://dev.to/simerplaha/functions-as-queries-swaydb-538n).
- `Bag.Less` - The effect type for all API calls. We can use [Cats](https://github.com/typelevel/cats-effect), [Monix](https://github.com/monix/monix), [ZIO](https://github.com/zio/zio), `Try`, `Future` or any other custom effect type. Using `Bag.Less` disables effect management and simply returns the result as output.

## Creating Tables
The following creates two tables under the root map.
```scala
val usersTable = map.schema.init(mapKey = "Users Table")  
val productsTable = map.schema.init(mapKey = "Products Table")

//this create another child table under Users Table.
val userTablesChild = usersTable.schema.init(mapKey = "Users Table's child")

//read all tables keys of userTable
val keys: Stream[String] = usersTable.schema.keys
//read all child tables of userTable
val tables = usersTable.schema.stream
```
##### Schema tree

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/5cg2a92jklovaon23ue5.png)

## Creating tables with default expiration

Similar to above we can also create Tables/Maps that expire. 

```scala
import scala.concurrent.duration._  
  
map.schema.init(mapKey = "Users Table", expireAfter = 10.days)  
map.schema.init(mapKey = "Products Table", expireAt = 10.seconds.fromNow)
```

## Removing and replacing tables
Replace creates a new table clearing all existing data including all existing child tables. 

```scala
//replace
map.schema.replace(mapKey = "Users Table", expireAfter = 10.days)

//or remove to delete the map/table
map.schema.remove(mapKey = "Users Table")
```

## Transactions

Modifications to multiple Tables can be performed as a single batch transaction. The following snippet creates and commits two transaction entries for two different tables.
```scala
//prepare statement for userTable and productTable  
val transaction =  
  usersTable.toTransaction(Prepare.Put(key = 1L, value = "user1")) ++  
    productsTable.toTransaction(Prepare.Put(key = 1L, value = "product1"))  
  
//commit to root map  
map.commit(transaction)  
  
usersTable.get(1L) shouldBe Some("user1")  
productsTable.get(1L) shouldBe Some("product1")
```
See [transaction](https://swaydb.simer.au/api/write/transaction/?language=scala/) for a list of all `Prepare` statements.

## Code

See [MultiMap_Example.scala](https://github.com/simerplaha/SwayDB.scala.examples/blob/master/src/test/scala/multimapExample/MultiMap_Example.scala) on Github which uses custom types with `circe` for serialisation. 

Please consider staring the [SwayDB](https://github.com/simerplaha/SwayDB) project if you find it useful.

## EAP
`MultiMap` is currently in preview version (EAP). See performance improvement task [#235](https://github.com/simerplaha/SwayDB/issues/235).

## GitHub repos

Check out related GitHub repos

-   [SwayDB](https://github.com/simerplaha/SwayDB) on GitHub.
-   [Scala](https://github.com/simerplaha/SwayDB.scala.examples)  examples repo.
-   [Java](https://github.com/simerplaha/SwayDB.java.examples)  examples repo.
-   [Kotlin](https://github.com/simerplaha/SwayDB.kotlin.examples)  examples repo.
-   [Documentation](https://swaydb.simer.au/).