Introducing Asami: A Flexible, Multiplatform Graph Store for Clojure
In the landscape of data management, graph databases offer a powerful way to represent complex relationships. For developers in the Clojure ecosystem, Asami emerges as a flexible, multiplatform graph store designed to bridge the gap between the ease of schemaless data entry and the power of structured graph analytics.
Written in Clojure, Asami is designed to run identically across the Java Virtual Machine (JVM) and JavaScript platforms (including browsers and Node.js), making it a versatile choice for full-stack Clojure development.
Core Philosophy and Goals
Asami is built around several key architectural goals that prioritize flexibility and stability:
- Schema-less Data: Data can be loaded without prior knowledge of its structure, allowing for rapid evolution and easier ingestion of heterogeneous data.
- Stability through Immutability: The storage system utilizes immutable structures to ensure that write operations cannot lead to data corruption.
- Pluggable Storage: Similar to Datomic, Asami supports multiple storage backends. It currently offers two in-memory systems and durable storage for the JVM.
- Open World Assumption: Borrowing semantics from RDF, Asami operates on an Open World Assumption. This means the database does not assume that a lack of information implies falsehood, which complements its schemaless nature.
Key Features
Beyond its core philosophy, Asami provides a suite of features tailored for graph-heavy workloads:
Querying and Execution
Asami features a query API that is intentionally similar to a simplified version of Datomic. To optimize performance, it includes a query planner that analyzes queries to find the most efficient execution plan, though this can be disabled if manual control is required.
Graph Analytics
Asami provides internal mechanisms for efficient graph traversal. Key capabilities include:
- Transitive Closures: The ability to find all connected nodes across multiple hops.
- Subgraph Identification: Tools to identify and extract specific subgraphs from the larger dataset.
- Transitive Queries: Support for transitive properties using
+or*notation in queries (e.g., finding a "friend of a friend").
Ecosystem Integration
Asami integrates with Loom, a graph analysis library, via the asami-loom package. This allows developers to perform advanced analysis and even generate visual representations of their graphs (e.g., exporting to PDF).
Getting Started with Asami
Installation
Asami can be added to a project via deps.edn or Leiningen:
deps.edn
{:deps {org.clojars.quoll/asami {:mvn/version "2.3.4"}}}
project.clj
[org.clojars.quoll/asami "2.3.4"]
Basic Usage
Creating and interacting with a database is straightforward. You can initialize an in-memory database and transact data using a simple API:
(require '[asami.core :as d])
;; Create and connect
(def db-uri "asami:mem://dbname")
(d/create-database db-uri)
(def conn (d/connect db-uri))
;; Transact data
(def movies [{:movie/title "Explorers" :movie/release-year 1985}])
@(d/transact conn {:tx-data movies})
;; Query data
(def db (d/db conn))
(d/q '[:find ?title :where [?m :movie/title ?title]] db)
Handling Updates
Because Asami follows the Open World Assumption, attributes are multi-arity by default. To replace an existing attribute value (similar to a "closed world" update), developers can annotate the attribute name with a quote character (e.g., :movie/genre').
Advanced Storage and Tooling
Local Storage
For datasets that exceed memory capacity, Asami supports local disk storage (asami:local://dbname). Local databases use InternalNode objects rather than keywords for entity IDs to optimize memory usage, which is critical for databases that may reach gigabytes in size.
Command Line Interface (CLI)
Asami provides a CLI tool (buildable via GraalVM) that allows users to load data from EDN or JSON files and execute queries directly from the terminal. This is particularly useful for quick data exploration or managing local stores without writing a full Clojure application.
Summary Table: Asami at a Glance
| Feature | Implementation |
|---|---|
| Platforms | JVM, JavaScript (Node.js, Browser) |
| Schema | Schemaless (Optional schemas on roadmap) |
| Storage | In-memory, Local Disk (JVM) |
| Query Style | Datomic-like |
| Analytics | Subgraphs, Transitive Closures, Loom Integration |