yomp_db 0.9.1

Yomp DB - pure DART implementation of database with graph querying and replication support. Stores data in IndexedDB or in memory.

NOSQL database engine, with complex queries, event sourcing and replication support. Library has abstract storage mechanism. There are included storages for IndexedDB and pure memory.

See test folder for a lot of examples of usage.

Example use:

import 'package:yomp_db/yomp_db.dart' as ydb;
import "package:yomp_db/storages/indexeddb.dart" as ydb_idb;
...
ydb.Database db = new ydb.Database(new ydb_idb.StorageIndexedDB());
// create a new database named "yompdbsample" with version 1,
// with one store "cities" without indexes
await db.open("yompdbsample", 1, {"cities":[]});
// put several documents in
await db.putSingle("cities", 
			{"name":"New York","country":"USA"});
String docid = await db.putSingle("cities",
			{"name":"Paris","country":"France","capital":"yes"});
await db.putSingle("cities", 
			{"name":"Bordeaux","country":"France"});
// get object based on ID generated by yomp_db
Map obj = await db.getSingle("cities", docid);
expect(obj["name"],"Paris");
// close the database
await db.close();

QUERY

Library provides string based queries, which are used for get and del. Null string means everything.

Format

    BASIC               SAMPLE          DESRIPTION
     id               iuh658hUt8        select document via _id property
property = value     city = Děčín       property equals to value
property != value   city != Děčín       property doesn't equal to value
   !property          !capital          property missing, is equal to null

It's possible to setup query with multiple conditions, those conditions are divided by comma. Example: continent = Europe , capital = true which selects all capitals inside Europe. Spaces around condition and comma are mandatory.

Sample

// get records for query -> country == France && capital == yes
String q = "country = France , capital = yes";
List<Map> result = await db.get("cities",q).toList();
// we expect one result Paris
expect(result.length,1);
expect(result.first["name"],"Paris");

PERFORMANCE

The following result is in miliseconds so the number 7.789 means 7 miliseconds and 789 microseconds. Every query is run against two types of storage, IndexedDB non-indexed and fully indexed, in-Memory non-indexed and fully indexed. My data around rock bands ~ 100 records:

-IDB--- / -IDB-I- / -MEM--- / -MEM-I- : command
  0.623 /   0.577 /   0.065 /   0.060 : IRONS
  7.451 /   0.606 /   0.067 /   0.059 : name = Queen
  7.395 /   0.845 /   0.073 /   0.068 : id_genre = METAL
  8.189 /   3.433 /   0.275 /   0.261 : type = album
  9.595 /  10.368 /   0.690 /   0.666 : type != album
  8.122 /   7.920 /   0.071 /   0.066 : type = person , name = Steve Harris
  8.695 /   4.057 /   0.234 /   0.235 : type = person , name != Steve Harris
 10.953 /  10.917 /   0.886 /   0.879 : !born_as
  8.034 /   1.075 /   0.086 /   0.078 : !born_as , type = band

More interestingly few queries in 1000 fortune companies data set:

-IDB--- / -IDB-I- / -MEM--- / -MEM-I- : command
187.300 /   1.000 /   0.400 /   0.100 : NAME = Google
190.000 /   2.300 /   0.700 /   0.100 : PLACE = Mountain View
203.700 /  27.700 /   2.600 /   1.900 : STATE = CA
287.300 / 285.800 /  15.500 /  15.000 : STATE != CA
199.600 /  33.900 /   2.000 /   1.800 : STATE = CA , PLACE != Mountain View

EVENT SOURCING

yomp_db provides derived class for creating and changing data via events.

ydb.DatabaseES db = new ydb.DatabaseES(new ydb_idb.StorageIndexedDB());
await db.addEvents("cities",[{"id":"DECIN","name":"Děčín"}]);
await db.addEvents("cities",[{"id":"DECIN","country":"Czech Republic"}]);
await db.addEvents("cities",[{"id":"DECIN","+districts":"Bynov"}]);
await db.addEvents("cities",[{"id":"DECIN","+districts":"Boletice"}]);
List ls = await db.get("cities").toList();
//  ls contains one object which looks: 
  {   "_id":"DECIN",
      "name":"Děčín",
      "country":"Czech Republic",
      "districts":["Bynov","Boletice"]
  }

REPLICATION

The database could be synchronized with external source, usually server, by setting replication. Client application just derive the Replication object with correct actions and set it to database as replication end point. Then whenever just call replicate(); We have prepared:

  • Cloudant - 'lib/replicators/cloudant', see 'test/replication_cloudant_test.dart' for usage

Sample code with Cloudant, authentication is not necessary, when database is publicly accessible.

import "package:yomp_db/replicators/cloudant.dart" as ydb_rcl;
...
await db.open("yompdbsample", 1, {"cities":[]});
ydb_rcl.ReplicatorCloudant repi = new ydb_rcl.ReplicatorCloudant(/*url*/);
repi.setBasicAuthentication(/*username*/,/*password*/);
db.setReplication("cities",repi);
// now just replicate store cities 
await db.replicate("cities"); // sends update to server and retrieves news 

GIT

https://bitbucket.org/tomas-rokos/yomp

YOMP

Yomp is family of libraries created for data management for client and server development in Dart. The creation is based on pull model. The additions are done when needed, so there could be missing obvious methods, but they were just not needed so far.

Yomp is word for long-distance march carrying full kit.