Giter Site home page Giter Site logo

komodo's Introduction

Komodo

A Kotlin noSQL database with MVStore as the backend

Why?

This project was started fill a need for a lightweight, efficient database in Kotlin that could be deployed anywhere a JVM is available.

The key objectives are:

  • As few dependencies as possible
  • No SQL
  • Local file backend
  • Reactive API
  • Kotlin idioms
  • B-tree and R-tree indices

Backend

The underlying store is MVStore, from the H2 database project. This is a production quality, self-contained pure Java implementation of key-value stores. A version of MVStore compiled for Java 7 (and thus Android compatible) is included in the Komodo jar file so no dependencies are required.

POKO (Plain Old Kotlin Objects) interface

Each KoMap (equivalent to a table) in the database is intended to store one kind of object. The translation between the stored data (which will usually be in the form of simple arrays of bytes) and Kotlin objects is done by a a CODEC (Coder/decoder) which is specific to each object. There is no default serialization or mapping - a CODEC must be written for each KoMap. The CODEC is also responsible for specifying any indices used. Consequently Komodo does not depend on GSON, Jackson or any other serialization framework, however any standard serialisation technique can be used.

Indices

The KoMap itself is a map of primary keys (Long data type) to objects. Indices are implemented by creating secondary maps of keys (as generated by the CODEC) to primary keys. There can be multiple indices for each KoMap and all insertions, deletions and updates will update all indices automatically. Unique and non-unique indices are supported.

Usage

Komodo is published on Maven Central. Include in your gradle project:

dependencies {
    implementation "com.control-j:komodo:1.0.1"
}

A sample class follows:

import com.controlj.komodo.KeyWrapper
import com.controlj.komodo.KoCodec
import com.controlj.komodo.KoMap
import com.controlj.komodo.Komodo
import com.google.gson.Gson

/**
 * Copyright (C) Control-J Pty. Ltd. ACN 103594190
 * All rights reserved
 *
 * User: clyde
 * Date: 2019-05-31
 * Time: 15:01
 *
 * A class used to save info about a connected device
 *
 * @param key The device serial number
 * @param address The device address
 * @param serial The serial number
 * @param description A descriptive string
 */
data class Sample(
        val key: Long,
        val address: String,
        val serial: Int,
        var description: String,
        ) {
    fun save() {
        diMap.update(this)
    }

    fun delete() {
        diMap.delete(DeviceCodec.keyFor(this))
    }

    override fun toString(): String {
        return "Sample($name: S/N=$serial, $description)"
    }

    companion object {
        // the database would usually be provided externally
        val database by lazy { Komodo(File(".", "Sample").path) }
        private const val DB_MAP_NAME = "Sample"        // the name of the Komap
        private const val DB_INDEX_PRIMARY = "primary"  // primary key name
        private const val DB_INDEX_ADDRESS = "address"  // secondary key name
        internal val diMap: KoMap<Sample> by lazy { database.koMap(DB_MAP_NAME, DeviceCodec) }

        /**
         * Retrieve all the Sample objects in the database
         */
        fun getEntries(): Iterable<Sample> {
            return diMap.query(DB_INDEX_PRIMARY)
        }

        /**
         * Retrieve a single Sample by key
         */

        fun get(deviceKey: Long): Sample? {
            return diMap.read(DeviceCodec.keyFor(deviceKey))
        }

        /**
         *  retrieve a single sample by address
         */
        fun get(address: String): Sample? {
            val key = DeviceCodec.keyFor(address)
            return diMap.query(DB_INDEX_ADDRESS, key, key).firstOrNull()
        }

        /**
         * The Codec. It defines a primary and a secondary key. Gson is used as the serialiser
         */
        object DeviceCodec : KoCodec<Sample> {
            private val mapper = Gson()
            override fun encode(data: Sample, primaryKey: KeyWrapper): ByteArray {
                return mapper.toJson(data).toByteArray()
            }

            override fun decode(encodedData: ByteArray, primaryKey: KeyWrapper?): Sample {
                return mapper.fromJson(String(encodedData), Sample::class.java)
            }

            /**
             * Generate a KeyWrapper for the primary key
             */
            fun keyFor(sampleKey: Long): KeyWrapper {
                return KeyWrapper.of(sampleKey)
            }

            /**
             * Generate a key for the secondary key
             */
            fun keyFor(address: String): KeyWrapper {
                return KeyWrapper.of(address)
            }

            /**
             * Create a Keywrapper for a an object
             */
            fun keyFor(devInfo: Sample): KeyWrapper {
                return keyFor(devInfo.key)
            }

            /**
             * The list of indices
             */
            override val indices: List<KoCodec.Index<Sample>> = listOf(
                    // Primary index
                    object : KoCodec.Index<Sample> {
                        override val name: String = DB_INDEX_PRIMARY
                        override val unique: Boolean = true
                        override fun keyGen(data: Sample): KeyWrapper {
                            return keyFor(data)
                        }
                    },
                    // secondary index
                    object : KoCodec.Index<Sample> {
                        override val name: String = DB_INDEX_ADDRESS
                        override val unique: Boolean = true
                        override fun keyGen(data: Sample): KeyWrapper {
                            return keyFor(data.address)
                        }
                    }
            )
        }
    }
}

To be continued....

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.