zetabasejs
v1.1.75
Published
A NoSQL database for quick deployment.
Downloads
36
Maintainers
Readme
ZetabaseJS
A NoSQL database for quick deployment
Get started
Installation
npm install --save zetabasejs
Hello World
const Zetabase = require("zetabasejs")
const db = new Zetabase("database.json") //Specify a filename.
db.write('/', 'Hello World !!')
let data = db.read('/')
console.log("Read DB: ", data) // Read DB: Hello World !!
Structure
A data node contains 2 parts, data
& childNodes
.
Write
operation will update the value in data
, which can be retrieved by Read
function.
Append
operation will update the value in childNodes
, which can be retrieved by List
function.
Operations
All operations are synchronized.
Write
db.write('/path', data);
let retrieve = db.read('/path');
console.log(retrieve) //The data is retrieved already.
db.write('/path/notExistFolder/subFolder', data); //The missing path will be created automatically.
db.write('/wallet', {balance: 351.5, timestamp: 1565485663}) //Just write the object into db.
Read
let balance = db.read('/wallet') //Retrieve the value in data part.
Output: { balance: 351.5, timestamp: 1565485663 }
// The value will be null if empty.
Append
db.append('/cart', {productCode: '#704FV4', price: 30, timestamp: 1565485663})
db.append('/cart', {productCode: '#604PG4', price: 20.9, timestamp: 1565485703})
db.append('/cart', {productCode: '#204KJ4', price: 70.4, timestamp: 1565485710})
db.append('/cart', {productCode: '#304TI2', price: 3.9, timestamp: 1565485716})
//The objects will be added to the childNodes with an unique key.
List
//List all appended objects.
db.list('/cart', (product, key)=>{
console.log(`
Product: ${JSON.stringify(product)}
Key: ${key}
`)
})
Product: {"productCode":"#704FV4","price":30,"timestamp":1565485663,"key":"2b0941aab466211b1c0752719c3d693b"}
Key: 2b0941aab466211b1c0752719c3d693b
Product: {"productCode":"#604PG4","price":20.9,"timestamp":1565485703,"key":"0c0381d3010fa7197d1658733cf2002a"}
Key: 0c0381d3010fa7197d1658733cf2002a
...
//Nested list.
let receiptKey = db.append('/receipts', {customerId: '#c001', totalPrice: 53.6, timestamp: 1565485716})
db.append('/receipts/'+receiptKey, {productCode: '#704FV4', price: 30, timestamp: 1565485663})
db.append('/receipts/'+receiptKey, {productCode: '#604PG4', price: 20.9, timestamp: 1565485703})
db.append('/receipts/'+receiptKey, {productCode: '#204KJ4', price: 70.4, timestamp: 1565485710})
db.append('/receipts/'+receiptKey, {productCode: '#304TI2', price: 3.9, timestamp: 1565485716})
db.list('/receipts', (receipt, key, products_dataNode)=>{
products_dataNode.list(product=>console.log(`
'Product code:', ${product.productCode},
'Price:', ${product.price},
'Timestamp:', ${product.timestamp}
`))
})
Wipe
//The empty folder will be removed automatically.
db.write('/A/B', 'Content in B')
db.write('/A/B/C/D', 'Content in D')
// In memory
{
"data": null,
"childNodes": {
"A": {
"id": "A",
"data": null,
"childNodes": {
"B": {
"id": "B",
"data": "Content in B",
"childNodes": {
"C": {
"id": "C",
"data": null,
"childNodes": {
"D": {
"id": "D",
"data": "Content in D",
"childNodes": {}
}
}
}
}
}
}
}
}
}
db.wipe('/A/B/C/D')
// In memory, folder C is removed automatically
{
"data": null,
"childNodes": {
"A": {
"id": "A",
"data": null,
"childNodes": {
"B": {
"id": "B",
"data": "Content in B",
"childNodes": {}
}
}
}
}
}
Query
let aliceId = db.append("/Customers", { name: "Alice", gender: "F" })
let katyId = db.append("/Customers", { name: "Katy", gender: "F" })
let bobId = db.append("/Customers", { name: "Bob", gender: "M" })
let tomId = db.append("/Customers", { name: "Tom", gender: "-" })
let waterId = db.append("/Product/drinks", { name: "Water", description: "300ml" })
let breadId = db.append("/Product/foods", { name: "Bread" })
db.append("/Transactions", {
customerId: aliceId, products: [
{ productCode: waterId, quantity: 10 },
{ productCode: breadId, quantity: 6 },
]
})
db.append("/Transactions", {
customerId: bobId, products: [
{ productCode: breadId, quantity: 40 }
]
})
// Query all female/not gender specified customers
let customers = db.query("/Customers/:key/@{name, gender}", {
gender: val => ['F', '-'].includes(val)
})
// Output
// [ { name: 'Alice', gender: 'F' },
// { name: 'Katy', gender: 'F' },
// { name: 'Tom', gender: '-' } ]
// Query all transactions for Alice and Katy
let transactions = db.query("/Transactions/:key/@{}", {
customerId: val => [aliceId, katyId].includes(val)
})
// Output
// [ { customerId: '6a7b5c84159b2e05837a2c4a3fcf5a6b',
// products: [ [Object], [Object] ],
// key: '9d705f589d16f6e69067679f479bab2f' } ]
// Query all transactions that contains water.
transactions = db.query("/Transactions/:key/@{}", {
products: val => val.filter(v => v.productCode == waterId).length > 0
})
transactions.map(trans => {
let cust = db.read("/Customers/" + trans.customerId)
console.log(`Customer:\t${cust.name}`)
console.log(`Product:\t${JSON.stringify(trans.products, null, 2)}`)
})
// Output
// Customer: Alice
// Product: [
// {
// "productCode": "17978e7bdb1b9eb1deffa6e37883c34a8DEbA",
// "quantity": 10
// },
// {
// "productCode": "fd08c2ebcef2c7243017a058ad650f898DEbA",
// "quantity": 6
// }
// ]
Monitor
Monitor changes in that level only.
// There are 3 action codes, WRITE, APPEND and WIPE
db.monitor('/Supermarket/status', status=>console.log("Supermarket's status is changed: ", status))
db.monitor('/Supermarket/purchaseOrder', (order, actCode) => {
if (actCode === "APPEND") {
console.log(`
An order is made.\n
orderId:, ${order.id},
totalAmount:, ${order.totalAmount}
`)
} else if (actCode === "WIPE") {
console.log(`
This order is cancelled.\n
orderId:, ${order.id},
totalAmount:, ${order.totalAmount}
`)
}
})
let orderKey = db.append('/Supermarket/purchaseOrder', { id: '#o001', totalAmount: 100 })
// Output
// An order is made.
// orderId:, #o001,
// totalAmount:, 100
db.wipe('/Supermarket/purchaseOrder/'+orderKey)
// Output
// This order is cancelled.
// orderId:, #o001,
// totalAmount:, 100
db.write('/Supermarket/status', 'Closed');
// Output
// Supermarket's status is changed: Closed
Modules
ORM
const Zetabase = require("zetabasejs")
const crypto = require('crypto')
// Require the Model class, which contains 3 properties
// __ctime__: creation time
// __mtime__: last modify time
// __key__: entity's key
const { Model } = require("zetabasejs/orm")
// Pass option { orm: true } to Zetabase constructor
// Default is false
const db = new Zetabase('./ormDemo.json', { orm: true })
//
class Product extends Model {
constructor(name, productCode, price) {
super()
this.name = name;
this.productCode = productCode;
this.price = price;
}
description() {
console.log(`Product name: ${this.name}, Product Code: ${this.productCode}, Price: ${this.price}`)
}
}
db.wipe('/')
for (let i = 0; i < 5; i++) {
let name = {
en: crypto.randomBytes(2).toString('hex'),
zh: crypto.randomBytes(4).toString('hex')
}
new Product(name, crypto.randomBytes(8).toString('hex'),
Math.floor(Math.random() * 100) + 1).put()
}
let options = {
filters: { price: v => v > 50 }, //Filter
fields: '{__key__, name, name.zh, productCode, price}', // Select the response value, default is all.
get: false //Default is true, which return an instance. Set to false to return the object contains the selected fields only.
}
let prods = Product.query(options); //Pass options object as params
// prods
[
{
__key__: '350295370a6b98fb63cc0c8495f00984',
name: { en: 'b3ca', zh: 'c3700382' },
'name.zh': 'c3700382',
productCode: '2bc6fb0714f2585e',
price: 95
},
{
__key__: 'eba710dc0a6185b6512ba0dfad2d75a3',
name: { en: '55ab', zh: '206a6a6e' },
'name.zh': '206a6a6e',
productCode: '52ac26b1796b657d',
price: 93
}
]
let firstProd = prods[0] //The query result is an object.
firstProd.description()
// firstProd
Product {
__ctime__: 1574498716475000,
__mtime__: 1574498716475000,
__key__: '350295370a6b98fb63cc0c8495f00984',
name: { en: 'b3ca', zh: 'c3700382' },
productCode: '2bc6fb0714f2585e',
price: 95
}
//Output Product name: [object Object], Product Code: 8b81f7f2d494d061, Price: 90