mindplay/jsondoc
Simple, file-based object/document-database using JSON-files for persistence., (*1)
, (*2)
, (*3)
, (*4)
Overview
Object-graphs are serialized and stored as JSON-documents, in individual files -
the JSON representations are (optionally, by default) indented and formatted in a
human-readable and CVS-friendly way., (*5)
Object-keys map directly to folders and file-names - for example, an object
stored as foo/bar
is saved as {database name}/foo/bar.json
., (*6)
Write and delete-operations are committed using basic transaction semantics,
with simple database-level locking to prevent simultaneous writes, using
early error-detection and automatic roll-back on failure., (*7)
Please see "Limitations" below for additional technical details., (*8)
API
The API consists of two classes:, (*9)
DocumentStore
represents the "connection" to a data-store: a root-folder
containing one or more databases., (*10)
DocumentSession
represents a session with one specific database inside a
data-store - it manages the loading and saving of objects, and attempts
to do so in a transactional and safe manner, e.g. committing all
save/delete operations atomically., (*11)
Usage
Create a DocumentStore with FilePersistence and point it to an existing folder:, (*12)
$store = new DocumentStore(new FilePersistence($db_path));
Ask the DocumentStore to create a DocumentSession:, (*13)
$session = $store->openSession();
This will lock the store in shared mode, until you close()
the session. (it will
also automatically close if it falls out of scope.), (*14)
Now create objects of any class, and store them:, (*15)
$a = new Foo;
$a->bar = 'Hello, World.';
$session->store($a, 'foo/bar');
Note that the state of the object has been captured in-memory, but the serialized
object does not get written to underlying storage until changes are committed., (*16)
Alternatively, you can store an object with a generated UUID under a parent ID:, (*17)
$a = new Foo;
$a->bar = 'Hello again!';
$id = $session->append($a, 'foo', $uuid);
var_dump($uuid); // "029d97a2-7676-45b1-9d49-353bec0d71c0"
var_dump($id); // "foo/029d97a2-7676-45b1-9d49-353bec0d71c0"
Load objects from the database into the current session:, (*18)
$b = $session->load('foo/baz');
Delete unwanted objects:, (*19)
$session->delete('foo/baz');
Call commit()
to persist all the pending store/delete-operations:, (*20)
$session->commit();
Finally, you should close()
to explicitly release the lock:, (*21)
$session->close();
The DocumentSession
API also provides a few other operations:, (*22)
-
exists($id)
indicates whether a document with the given ID exists in the store., (*23)
-
contains($id)
indicates whether the session contains a document with a given ID., (*24)
-
getId($object)
provides the document ID of an object in the session., (*25)
-
evict($id)
evicts the object/document with the given ID from the session., (*26)
-
flush()
evicts all objects/documents and pending operations from the session., (*27)
Limitations
Using individual, flat files for data-storage is not fast - this
library (by design) is optimized for consistent storage, quick and
easy implementation, human-readable and VCS-compatible file-based
storage, in applications where speed is not a critical factor., (*28)
The JsonSerializer itself has an important limitation: it is designed
to store self-contained object-graphs only - it does not support shared
or circular object-references. This is by design, and in-tune with good
DDD design practices: an object-graph with shared or circular references
does not have clear transaction boundaries and cannot be stored in a
predictable and consistent way., (*29)
This library does not synthesize object keys - which means you must
assign a key when you store a new object. Again, this is by design., (*30)
More detailed background on limitations and technical decisions
here., (*31)