DBO: Persistent data abstraction module

DBO.connect

Connects to the mySQL database that will be used.

var DBO = require("dbo");

DBO.connect({host: "127.0.0.1",	user: "myuser", password : "mypassword", database: "mydb"});

DBO.List

Creates a list of all the rows in a database table. Each item in the list will be an object.

var players = new DBO.List({table: "player", fun: Player, key: "name"});

for(var name in players) {
	console.log(players[name].data.name);
	console.log(players[name].data.score);
}

The key should be the primary key of the database table (that can only be one field).
If no key is specified, lower case "id" will be used.

The function will be used to create the object.

If no function is specified, A new Object() will be used.

If DBO.cfg.asyncListsCreation is set to true, a callback can be set as a second argument.

.add

Adds a object to the list.

players.add({name: "Jon Doe", age: 33});

Makes an INSERT into the database table specified when creating the list. And create a new Object with the constructor specified when making the list.

Returns the added object.

Tip: For convenience, use default values for most fields in the database!

.link

Makes data from one list accessible in another based on their relation.

var players = new DBO.List({table: "player", fun: Player});
var shares = new DBO.List({table: "shares"});

players.link({list: shares, key: "player", attribute: "shareholders", pp: "issuer"});
players.link({list: shares, key: "owner", attribute: "investments"});

Player.prototype.showShareHolders = function() {
	var player = this;
	
	for(var share in player.shareholders) {
		showInfo( player.shareholders[share] );
	}
	
	function showInfo(share) {
		console.log(share.owner.data.name + " owns " + share.data.shares + 
		" share with a total worth of " + share.data.price);
	}
}

This will create a list of shareholders and investments under each player.

For convenience, the pp will be accessible from each share.
If pp is not defined, the key will be used.
This will however create a circular structure and can be disabled by defining pp to false, or for all links by setting DBA.cnf.pointToParentInLinks to false.

.kill

This will remove an object from the list.

players.kill("Jon Doe");

The primary key need to be passed as argument.

Note that you should kill the child's before killing the parent:

for(var id in players["Jon Doe"].armies) {
	armies.kill(id);	
}
players.kill("Jon Doe");

.has

Returns true if the list has all the property:value's in argument object.

if(!players.has({id: id, name: "Arnold"}) ...

Use obj.has instead of obj.hasOwnProperty

.filter

Will return a list of all objects that matches the criteria of the argument function.

// Find all players that are between 45 and 64
var middleAge = players.filter(function filterMiddleAge(player) {
	return player.data.age >= 45 && player.data.age <= 65;
});

.find

Finds a object in the list that matches the property:value in the argument object.

// Find all players that are 35 years old AND drinks beer
partyPpl = players.find({age: 35, drink: "beer"});

Equalent of SQL: SELECT * FROM players WHERE age = 35 AND drink = "beer" AND ...

Use .filter for more advanced search

.random

Returns a random object from the list.

randomPlayer = players.random();
console.log(randomPlayer.data.name);

.first

Checks if the list only has one object and returns that object.

var player = players.find({login: login, pw: pw}).first();
if(player) {
	console.log("Hello " + player.data.name + "!");
}

Returns false if no object exist.

.count

Returns number of objects in the list. Accepts a property:value object as argument.

var totalPlayers = players.count();
var totalElves = players.count({race: "elf"});

.sum

Summarizes a data object in a list.

var income = players["Arnold"].cities.sum("productionIncome");

.shuffledKeys

Returns an array of shuffled objects

var deck = cards.shuffledKeys();

.sortedKeys

Returns an array of sorted objects.

var arrPlayers = players.sort({age: "ASC", name: "DESC"});

.branch

Returns a branch of the List. Used internally in .link, .find, and .filter. So you can make function chains.

DBO.Array

Modified JS Array to hold the data.

Useful if you want a pure Array instead of a object literal.

Example use would be a game world map, where x, y are the dimensions.

var spacemap = new DBO.Array();

spacemap.load({table: "spacemap", dimensions: ["x", "y"], fun: Spaceobject}, false);
spacemap.add({x: 0, y:2, type:"asteroid", type_id: 71});
console.log("spacemap.length=" + spacemap.length);
console.log(JSON.stringify(spacemap, null, 2));

If the Array will have holes in it (Posts might be deleted), consider using DBO.List instead.

DBO.Log

Works like DBO.List, but do not keep the data in memory. Only the amount of inserts are saved. Intended use for statistics of huge data that do not fit in memory, or like a time series database.

var attacks = new DBO.Log({table: attacks, keys: [attacker, defender]});
	
	attacks.add({attacker: playerId, defender: anotherPlayer}); 
	
	console.log( "Total attacks made by player " + playerId + ": " + 
    attacks.count({attacker: playerId}) );
	
	console.log( "Total attacks made by player " + playerId + " on player " + 
    otherPlayer + ": " + attacks.count({attacker: playerId, defender: otherPlayer}) );
	

.add

Adds data to the log.

.count

Counts data entries. Works like a SELECT Count(*). But without the database round-trip!

The value can be retrieved directly without calling .count:

	console.log("Total attacks made by player " + playerId + ": " + attacks["attacker"][playerId].__total;
	
console.log( "Total attacks made by player " + playerId + " on player " + otherPlayer + ": " + 
    attacks["attacker"][playerId]["defender"][otherPlayer]) );
	

.list

Select only a part of the log

	console.log(JSON.stringify(attacks.list({attacker: playerId}), null, 2));
	

DBO.Table

DBO.Table is used internally to hold the data in a key:value table.

	var player = new Player();
	player.data = new DBO.Table({table: "player", keys: {name: "Johan"}}, doStuff);
	
	function doStuff() {
		player.doSomething();
	}
	

Selects all data from table player where name equals "Johan".

Update the data

	player.data.score = player.data.score + 1;
	

A Object defined setter works in the background and makes an async database UPDATE.

Debugging

	DBO.debug.showSQL = true;
	DBO.debug.showWarnings = true;
	DBO.debug.useColors = true;
	

"Offline mode"

When creating a DBO.List or DBO.Log, specify table: false.

No updates will be pushed to the database.
Useful if you just want to test something or write a quick demo.