nor-nopg
This is a Node.js library which implements NoSQL features over a PostgreSQL v9.3 database.
Usage
var nopg = ;
Before using the database you should initialize it by calling: nor-nopg --pg=psql://localhost:5432/test init
See also
- nor-app -- provides a HTTP interface in to a nor-nopg database
- nopg -- Shell scripting CLI for nor-nopg
Summary
Variable names used in this document
Name | Description | Example |
---|---|---|
NoPg |
NoPg module |
var NoPg = require('nor-nopg'); |
db |
NoPg instance |
NoPg.start(...).then(function(db) { ... }); |
doc |
NoPg.Document instance |
db.create()(...).shift().then(function(doc) { ... }); |
type |
NoPg.Type instance |
db.declareType("name")().shift().then(function(type) { ... }); |
Summary of available operations
Short usage | Description | Tested at |
---|---|---|
NoPg.start(...) |
Get connection and start transaction | L42 |
db.init() |
Initialize database | L15 |
db.create()({"hello":"world"}) |
Create document without type | L41 |
db.create("MyType")({"hello":"world"}) |
Create document with type as string | L57 |
db.create(type)({"hello":"world"}) |
Create document with type as object | L306 |
db.search()({"$id": "b58e402e-6b39-11e3-99c7-0800279ca880"}) |
Search documents by id | L156 |
db.search()({"hello": "world"}) |
Search documents by values | L130 |
db.search()(function(doc) { return doc.hello === 'world'; }) |
Search documents by custom function | |
db.search("Foobar")() |
Search documents by type string | L185 |
db.search("Foobar")({"name":"hello"}) |
Search documents by type string with values | L219 |
db.search(type)() |
Search documents by type | |
db.search(type)({"name":"hello"}) |
Search documents by type as string with values | L254 |
db.update(doc) |
Edit document by instance of NoPg.Document | L93 |
db.update(doc, {"hello": "world"}) |
Edit document by plain document | L74 |
n/a | Edit documents by type | |
db.del(doc) |
Delete document by instance of NoPg.Document | L113 |
n/a | Delete documents by instance of NoPg.Type | |
db.del(type) |
Delete type by instance of NoPg.Type | L400 |
db.del(attachment) |
Delete attachment | |
db.declareType("Product")({"$schema":{"type":"object"}}) |
Create or replace type with name as string | |
db.createType("Product")({"$schema":{"type":"object"}}) |
Create type with name as string | |
db.createType()({"$schema":{"type":"object"}}) |
Create type without name | |
db.update(type) |
Edit type by instance of NoPg.Type | Yes |
db.update(type, {$schema:{...}}) |
Edit type by plain object | Yes |
db.searchTypes({"$id": "b58e402e-6b39-11e3-99c7-0800279ca880"}) |
Search types | |
doc.createAttachment(data, {"content-type": "image/png"}) |
Create attachments | |
doc.searchAttachments() |
Search attachments | |
doc.getAttachment("b58e402e-6b39-11e3-99c7-0800279ca880") |
Search attachments | |
db.import('/path/to/tv4.js', {'$name': 'tv4'}) |
Import or upgrade module in database |
PostgreSQL and JavaScript name mapping
PostgreSQL | JavaScript | Description |
---|---|---|
id |
obj.$id |
Property with leading $ is mapped to the actual database table column |
content->>'name' or content->'name' |
obj.name |
Property without leading $ is mapped to the property of the primary JSON data variable. It's content for NoPg.Document s and meta for other objects. The string or number operator is detected automatically from the type of the value. |
Connections and transactions
nopgstart'postgres://user:pass@localhost/dbname';
You must call
db.commit()
to actually save any changes to the database; ordb.rollback()
to cancel the transaction
Initialize database
The required table structures and initial settings and data can be created or upgraded
by calling db.init()
:
nopgstartPGCONFIG;
Events
NoPG (from v1.1.0) has integrated support for events using PostgreSQL's tcn extension.
Please note: You need to use .connect()
instead of .start(...)
, since
listening in a transaction will block other threads!
Type#create
Event: - Listener gets arguments:
id
- UUID of the document which has been createdeventName
- Name of the eventtype
- Type name
nopg;
<Type>#<ID>@<eventName>
Event: - Listener gets arguments:
id
- UUID of the document which has been createdeventName
- Name of the eventtype
- Type name
nopg;
Type#update
Event: - Listener gets arguments:
id
- UUID of the document which has been changedeventName
- Name of the eventtype
- Type name
Type#deleteType
Event: - Listener gets arguments:
id
- UUID of the type which has been deletedeventName
- Name of the eventtype
- Type name
create
Event: - Listener gets arguments:
id
- UUID of the document which has been createdeventName
- Name of the event
nopg;
update
Event: - Listener gets arguments:
id
- UUID of the document which has been changedeventName
- Name of the event
delete
Event: - Listener gets arguments:
id
- UUID of the document which has been deletedeventName
- Name of the event
createType
Event: - Listener gets arguments:
id
- UUID of the type which has been createdeventName
- Name of the event
updateType
Event: - Listener gets arguments:
id
- UUID of the type which has been changedeventName
- Name of the event
deleteType
Event: - Listener gets arguments:
id
- UUID of the type which has been deletedeventName
- Name of the event
createAttachment
Event: - Listener gets arguments:
id
- UUID of the attachment which has been createdeventName
- Name of the event
updateAttachment
Event: - Listener gets arguments:
id
- UUID of the attachment which has been changedeventName
- Name of the event
deleteAttachment
Event: - Listener gets arguments:
id
- UUID of the attachment which has been deletedeventName
- Name of the event
createLib
Event: - Listener gets arguments:
id
- UUID of the lib which has been createdeventName
- Name of the event
updateLib
Event: - Listener gets arguments:
id
- UUID of the lib which has been changedeventName
- Name of the event
deleteLib
Event: - Listener gets arguments:
id
- UUID of the lib which has been deletedeventName
- Name of the event
Non-TCN events
We also implement few events which are not through PostgreSQL. These will happen only on the local instance.
disconnect
Event: When connection will be disconnected.
commit
Event: When transaction has been commited.
rollback
Event: When transaction has been rollback'd.
User-defined events
If you want your application to use custom LISTEN
or NOTIFY
, we recommend
directly using
nor-pg
. It has a
nice familiar interface for it.
There is no reason to implement this feature in NoPG since implementing it
wouldn't invent anything new; it would be direct wrapper for nor-pg
.
Our promise implementation
We use an extended promise implementation which allows chaining of multiple methods together.
Under the hood we are using q
promises
which are extended using nor-extend
.
However these extended features are not required. You may use our promises just like any other q-promises.
Example of chaining multiple asynchronic calls together
NoPgstart..."name":"Bar""name":"Foo";
About the PostgreSQL ORM Mapping
The module has simple ORM mappings for all of our PostgreSQL tables.
JavaScript constructor | PostgreSQL table | Default JSON column |
---|---|---|
NoPg.Document |
documents |
content |
NoPg.Type |
types |
meta |
NoPg.Attachment |
attachments |
meta |
NoPg.Lib |
libs |
meta |
NoPg.Method |
methods |
meta |
NoPg.DBVersion |
dbversions |
n/a |
Using database constructors
These constructors will take an object and convert it to JavaScript instance of that PostgreSQL table row.
Example object:
"name": "Hello" "foo": "bar" "age": 10 "$id": "8a567836-72be-11e3-be5d-0800279ca880" "$created": "" "$updated": ""
The special $
in the name makes it possible to point directly to a column
in PostgreSQL row.
Any other property points to the column in default JSON column.
For example a obj.$meta.foo
in NoPg.Type
instance has the same value as
obj.foo
unless the ORM instance has been changed by the user.
Documents
Create document
Create document without type
db"hello":"world";
Create document with type as string
db"hello":"world";
Tested at test-nopg.js:57.
Create document with type as object
db"hello":"world";
Search documents
Search documents by id
db"$id": "b58e402e-6b39-11e3-99c7-0800279ca880";
Search documents by values
db"hello": "world";
Search documents by custom function
db { return dochello === 'world';};
Search documents by type string
db;
Search documents by type string with values
db"name":"hello";
Search documents by type
db;
Edit documents
NoPg.Document
Edit document by instance of dochello = "world"; db;
Tested at test-nopg.js:93.
Edit document by plain document
db;
Tested at test-nopg.js:74.
Edit documents by type
/* n/a */
Delete documents
NoPg.Document
Delete document by instance of db;
Tested at test-nopg.js:113.
NoPg.Type
Delete documents by instance of // n/a
NoPg.Type
Delete type by instance of db;
Delete attachment
db;
Types
Create types
Create or replace type with name as string
db"schema":"type":"object";
Create a new type with name as string
db"schema":"type":"object";
Create type without name
db"schema":"type":"object";
Edit types
NoPg.Type
Edit type by instance of typeschema = ;db;
Edit type by plain object
db;
Search types
db;
Attachments
Create attachments
nopgfile "content-type": "image/png";
- If
doc
isundefined
then document is looked from previous value in the buffer which must bynopg.Attachment
ornopg.Document
.
Search attachments
Search all attachments
docopts;
- If you omit doc, the last element in the queue will be used.
- If you omit opts, then all attachments are listed otherwise only matching.
Get attachment by ID
doc;
Libs
Import or upgrade module in the database
db;
Run tests
Database configurations can be set using PGCONFIG:
export PGCONFIG='pg://user:password@localhost/db'
The actual test can be run: npm test
You must delete the data if you need to run the test suite again for the same database:
psql -q db < scripts/cleanup.sql
Please note: psql does not follow PGCONFIG
environment variable!
Run lint test
npm run lint
Commercial Support
You can buy commercial support from Sendanor.
TODO
We use Trello board to organize development and keep track on things to do.
Internal Database Schema
dbversions
Table Name | Type |
---|---|
version |
integer |
modified |
timestamptz |
types
Table Name | Type |
---|---|
id |
uuid |
name |
text |
schema |
json |
validator |
text |
meta |
json |
created |
timestamptz |
modified |
timestamptz |
methods
Table Name | Type |
---|---|
id |
uuid |
types_id |
uuid |
type |
text |
name |
text |
body |
text |
meta |
json |
active |
boolean |
created |
timestamptz |
modified |
timestamptz |
documents
Table Name | Type |
---|---|
id |
uuid |
content |
json |
types_id |
uuid |
created |
timestamptz |
modified |
timestamptz |
type |
text |
attachments
Table Name | Type |
---|---|
id |
uuid |
documents_id |
uuid |
content |
bytea |
meta |
json |
created |
timestamptz |
modified |
timestamptz |
libs
Table Name | Type |
---|---|
id |
uuid |
name |
text |
content |
text |
meta |
json |
created |
timestamptz |
modified |
timestamptz |
Obsolete entity relationship diagram
This database structure has not been updated.