Query Builder: DB() och NEWDB() med din egen databasdrivare
DB() bygger en fråga utan att veta vilken databas som ska köra den, och NEWDB() registrerar drivrutinen som kör den. total5 självt har ingen SQL-drivrutin: query buildern samlar det du ber om i ett options-objekt och anropar din drivrutin med det, och drivrutinen (din egen, eller en som kommer i en modul) översätter options till SQL, ett NoSQL-anrop eller något annat.
NEWDB(driver)registrerar standarddrivrutinen ochNEWDB('name', driver)en namngiven. Drivrutinen ärfunction(options, callback): svara medcallback(error, response). En tabell skriven somname/table(DB().find('audit/log')) använder drivrutinennameoch tabellenlog; utan prefix är drivrutinendefault.- Operationen börjar med frågan:
find(table)(och i ett par fall)read(table)ett objekt, ellernullNär det inte finns någon,list(table)(en sida av en array:response.page,limitochpagessom läggs till vad föraren returnerar, så föraren bör ställa incount) ochinsert(table, data)Byggaren har ocksåcount,update,removeochqueryDe arbetar på samma sätt (föraren fåroptions.execmed det namnet) - Upprepa frågan med:
where(name, [comparer], value)(=När det inte finns någon jämförelse,fields('a,b'),sort(name, [true])(trueför att föra ner,take(n)ochpage(page, limit)Andra modifieringar inkluderarid,in,skip,betweenochsearch. - Avsluta med
.callback($): resultatet går till svaret från åtgärden$, eller till en funktion(err, response)som du skickar i stället.
För den fullständiga inhemska verksamhetskatalogen, uppblåst/fel beteende och filterformer, se Fråga-kontraktFör SQL CRUD, commit och rollback, se Fråga-byggare-sqliteDe alternativ som föraren får är tydliga data. exemplet föraren lagrar anteckningar i minnet och exponerar det senaste options-objektet som mottagits.
const users = [
{ id: 1, name: 'Ann', age: 31 },
{ id: 2, name: 'Bob', age: 17 },
{ id: 3, name: 'Cy', age: 45 }
];
F.seen = [];
// The default driver: it understands only "age >= value" and "id = value", which is all this example asks
NEWDB(function(options, callback) {
F.seen.push(JSON.parse(JSON.stringify(options)));
let rows = users.slice();
for (let f of options.filter) {
if (f.type === 'where' && f.name === 'age' && f.comparer === '>=')
rows = rows.filter(n => n.age >= f.value);
else if (f.type === 'where' && f.name === 'id')
rows = rows.filter(n => n.id === f.value);
}
switch (options.exec) {
case 'find':
case 'read':
if (options.sort && options.sort[0] === 'name_desc')
rows.sort((a, b) => a.name < b.name ? 1 : -1);
if (options.take)
rows = rows.slice(0, options.take);
return callback(null, rows);
case 'list':
rows.count = rows.length;
return callback(null, rows);
case 'insert':
users.push(Object.assign({ id: users.length + 1 }, options.payload));
return callback(null, users[users.length - 1]);
default:
return callback('The driver does not know ' + options.exec);
}
});
// A second driver, used by the tables that start with "audit/"
NEWDB('audit', function(options, callback) {
F.seen.push({ driver: 'audit', table: options.table });
callback(null, [{ event: 'login' }]);
});exports.install = function() {
ROUTE('GET /adults/', adults);
ROUTE('GET /user/{id}/', user);
ROUTE('POST /users/', create);
ROUTE('GET /page/', page);
ROUTE('GET /audit/', audit);
ROUTE('GET /seen/', seen);
};
function adults($) {
DB().find('users').where('age', '>=', 18).fields('id,name').sort('name', true).take(5).callback($);
}
function user($) {
DB().read('users').where('id', +$.params.id).callback($);
}
function create($) {
DB().insert('users', { name: $.body.name, age: $.body.age }).callback($);
}
function page($) {
DB().list('users').page(1, 2).callback(function(err, response) {
$.json({ err: err, count: response.count, page: response.page, limit: response.limit, pages: response.pages });
});
}
function audit($) {
DB().find('audit/log').callback($);
}
function seen($) {
$.json(F.seen);
}