2015-12-01 01:39:22 +00:00
|
|
|
Master Quest SQLite3
|
|
|
|
============
|
2015-09-22 02:14:26 +00:00
|
|
|
|
2015-12-01 01:39:22 +00:00
|
|
|
Master Quest is a brave new attempt at Data Mapping.
|
2015-09-22 02:14:26 +00:00
|
|
|
|
2015-12-01 01:39:22 +00:00
|
|
|
It kinda looks like an ORM, but it isn't. It's not SQL, it's NoSQL with benefits.
|
|
|
|
|
|
|
|
You get to choose which contraints to keep and which to forget.
|
|
|
|
|
|
|
|
Guiding Principles
|
|
|
|
|
|
|
|
* NoSQL (well, as far as you care)
|
|
|
|
* Migrations don't suck
|
|
|
|
* Harness the awesomeness of indexes
|
|
|
|
* `deletedAt` to delete a record
|
|
|
|
* `null` to delete a field
|
|
|
|
* unindexed fields stored as json
|
|
|
|
* ids should be one either
|
|
|
|
* deterministic (duplicate records not okay, last `updatedAt` wins)
|
|
|
|
* cryptographically random (duplicate records consolidated in application)
|
|
|
|
* avoid mutating data (CRDT-ish style)
|
|
|
|
* if it won't scale, don't fret it (no foreign key contraints)
|
|
|
|
* `id` is simply named `id`
|
|
|
|
* multi-key ids should be `sha256sum(key1 + key2 + key3)`
|
|
|
|
* JavaScript is `camelCase`y, databases are `snake_case`y. We can handle that.
|
|
|
|
* join tables are in alphabet order i.e. `foo`, `bar`, `bar_foo`
|
|
|
|
|
|
|
|
TODO / In Progress
|
|
|
|
|
|
|
|
* Multi-Master Replication
|
|
|
|
* Relationships
|
|
|
|
* currently detaches before saving (most important)
|
|
|
|
* MongoDB / RethinkDB -ish queries
|
|
|
|
* RealTime
|
|
|
|
|
|
|
|
USAGE
|
|
|
|
=====
|
|
|
|
|
|
|
|
```bash
|
|
|
|
npm install --save 'https://github.com/coolaj86/node-masterquest-sqlite3.git'
|
|
|
|
```
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
'use strict';
|
|
|
|
|
|
|
|
// works with sqlite3, sqlcipher, and sqlite3-cluster
|
|
|
|
var db = new (require('sqlite3').Database)('/tmp/data.sqlite3');
|
|
|
|
|
|
|
|
require('masterquest-sqlite3').wrap(db, {
|
|
|
|
modelname: 'Persons'
|
|
|
|
, indices: [ 'firstName', 'lastName' ]
|
|
|
|
, hasMany: [ 'children' ]
|
|
|
|
}).then(function (mq) {
|
|
|
|
|
|
|
|
// update (or create) deterministic record
|
|
|
|
var john = {
|
|
|
|
id: 'john.doe@email.com'
|
|
|
|
, firstName: 'john'
|
|
|
|
, lastName: 'doe'
|
|
|
|
, dog: { name: 'ralph', color: 'gold' }
|
|
|
|
, children: [ 'stacey@email.com' ]
|
|
|
|
};
|
|
|
|
|
|
|
|
mq.Persons.upsert(john.id, john).then(function () {
|
|
|
|
// note: if `dog` existed, it will be overwritten, not merged
|
|
|
|
// note: `children` will be removed before save
|
|
|
|
|
|
|
|
mq.Persons.get('john.doe@email.com').then(function (data) {
|
|
|
|
// dog will be rehydrated from json
|
|
|
|
// children will not be fetched and attached
|
|
|
|
console.log(data);
|
|
|
|
});
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
});
|
|
|
|
```
|
2015-09-22 02:14:26 +00:00
|
|
|
|
|
|
|
API
|
2015-12-01 01:39:22 +00:00
|
|
|
===
|
|
|
|
|
|
|
|
It's kinda CRUDdy... but don't let that scare you.
|
|
|
|
|
|
|
|
* `upsert(id, data)` - creates or updates based on existence in DB (use this)
|
|
|
|
* modifies `createdAt` and or `updatedAt`
|
2016-02-23 04:10:42 +00:00
|
|
|
* `create(id, obj)` - same as above, but fails if the object exists
|
2015-12-01 01:39:22 +00:00
|
|
|
* `save(data)` - (just don't use this, please) creates or updates based on presence of ID
|
|
|
|
* `destroy(id)` - mark a record as `deletedAt` from DB
|
|
|
|
* `get(id)` - grab one by id
|
|
|
|
* `find(attrs, opts)` - grab many by indexable attributes
|
|
|
|
* attrs
|
|
|
|
* explicit `null` will find all (and requires that `limit` be set)
|
|
|
|
* `{ foo: 2, bar: 6 }` will find records where `foo` is `2` *and* `bar` is `6`
|
|
|
|
* opts
|
|
|
|
* `orderBy`
|
|
|
|
* `orderByDesc`
|
|
|
|
* `limit`
|
|
|
|
|
|
|
|
Schema
|
|
|
|
======
|
|
|
|
|
|
|
|
Anything that isn't in the schema
|
|
|
|
|
|
|
|
* `indices` specifies an array of strings
|
|
|
|
* `[ 'firstName', 'lastName' ]`
|
|
|
|
* relationships are option and current only exclude during save
|
|
|
|
* `hasMany`, `belongsTo`, `hasOne`, `belongsToMany`, `hasAndBelongsToMany`
|
|
|
|
* `createdAt`, `updatedAt`, `deletedAt` timestamps are always added
|
|
|
|
* turn off with `timestamps: false`
|
|
|
|
* `id` is always `id`
|
|
|
|
* change with `idname: 'myId'`
|
|
|
|
|
|
|
|
Migrations
|
|
|
|
----------
|
|
|
|
|
|
|
|
You can only add indexes. You cannot rename or remove them.
|
|
|
|
|
|
|
|
To add an index, simply change the schema.
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
{ modelname: 'persons'
|
|
|
|
, indices: [ 'firstName', 'lastName' ]
|
|
|
|
, hasMany: [ 'children' ]
|
|
|
|
}
|
|
|
|
```
|
2015-09-22 02:14:26 +00:00
|
|
|
|
2015-12-01 01:39:22 +00:00
|
|
|
LICENSE
|
|
|
|
=======
|
2015-09-22 02:14:26 +00:00
|
|
|
|
2015-12-01 01:39:22 +00:00
|
|
|
Dual-licensed MIT and Apache-2.0
|
2015-09-22 02:14:26 +00:00
|
|
|
|
2015-12-01 01:39:22 +00:00
|
|
|
See LICENSE
|