zumito-db
Version:
Multi-driver database abstraction layer with decorator-based models
69 lines (68 loc) • 2.25 kB
JavaScript
import { toMongoOperator } from '../operators.js';
export class MongoCompiler {
compileFind(ir) {
const filter = this.compileWhere(ir.where);
const options = {};
if (ir.select && ir.select.length > 0) {
const projection = {};
for (const field of ir.select)
projection[field] = 1;
options.projection = projection;
}
if (ir.sort && ir.sort.length > 0) {
const sort = {};
for (const s of ir.sort)
sort[s.field] = s.dir === 'asc' ? 1 : -1;
options.sort = sort;
}
if (ir.limit)
options.limit = ir.limit;
if (ir.offset)
options.skip = ir.offset;
return { filter, options };
}
compileUpdate(data) {
return { $set: data };
}
compileWhere(clauses) {
if (!clauses || clauses.length === 0)
return {};
// Group by logic: split 'or' groups
const groups = [];
let currentGroup = [];
for (const clause of clauses) {
currentGroup.push(clause);
if (clause.logic === 'or') {
groups.push(currentGroup);
currentGroup = [];
}
}
if (currentGroup.length > 0)
groups.push(currentGroup);
if (groups.length === 1) {
const filter = {};
for (const clause of groups[0]) {
filter[clause.field] = this.compileClause(clause);
}
return filter;
}
return {
$or: groups.map(group => {
const filter = {};
for (const clause of group) {
filter[clause.field] = this.compileClause(clause);
}
return filter;
}),
};
}
compileClause(clause) {
if (clause.operator === 'eq')
return clause.value;
if (clause.operator === 'like')
return { $regex: clause.value, $options: 'i' };
if (clause.operator === 'between')
return { $gte: clause.value[0], $lte: clause.value[1] };
return { [toMongoOperator(clause.operator)]: clause.value };
}
}