mongo condition refactor

This commit is contained in:
Jan Prochazka
2024-08-19 15:31:54 +02:00
parent 8cffeaa767
commit 9fedfcbb0e
4 changed files with 119 additions and 6 deletions

View File

@@ -39,13 +39,15 @@ export const datetimeFilterBehaviour: FilterBehaviour = {
}; };
export const mongoFilterBehaviour: FilterBehaviour = { export const mongoFilterBehaviour: FilterBehaviour = {
compilerType: 'mongoCondition', compilerType: 'sqlTree',
supportEquals: true, supportEquals: true,
supportArrayTesting: true, supportArrayTesting: true,
supportNumberLikeComparison: true, supportNumberLikeComparison: true,
supportStringInclusion: true, supportStringInclusion: true,
supportBooleanValues: true, supportBooleanValues: true,
supportExistsTesting: true, supportExistsTesting: true,
allowStringToken: true,
}; };
export const evalFilterBehaviour: FilterBehaviour = { export const evalFilterBehaviour: FilterBehaviour = {

View File

@@ -33,11 +33,18 @@
const ast = parseFilter(filters[uniqueName], filterBehaviour); const ast = parseFilter(filters[uniqueName], filterBehaviour);
// console.log('AST', ast); // console.log('AST', ast);
const cond = _.cloneDeepWith(ast, expr => { const cond = _.cloneDeepWith(ast, expr => {
if (expr.__placeholder__) { if (expr.exprType == 'placeholder') {
return { return {
[uniqueName]: expr.__placeholder__, exprType: 'column',
columnName: uniqueName,
}; };
} }
// if (expr.__placeholder__) {
// return {
// [uniqueName]: expr.__placeholder__,
// };
// }
}); });
conditions.push(cond); conditions.push(cond);
} catch (err) { } catch (err) {
@@ -47,7 +54,8 @@
return conditions.length > 0 return conditions.length > 0
? { ? {
$and: conditions, conditionType: 'and',
conditions,
} }
: undefined; : undefined;
} }

View File

@@ -7,6 +7,7 @@ const MongoClient = require('mongodb').MongoClient;
const ObjectId = require('mongodb').ObjectId; const ObjectId = require('mongodb').ObjectId;
const AbstractCursor = require('mongodb').AbstractCursor; const AbstractCursor = require('mongodb').AbstractCursor;
const createBulkInsertStream = require('./createBulkInsertStream'); const createBulkInsertStream = require('./createBulkInsertStream');
const { convertToMongoCondition } = require('../frontend/convertToMongoCondition');
function transformMongoData(row) { function transformMongoData(row) {
return _.cloneDeepWith(row, (x) => { return _.cloneDeepWith(row, (x) => {
@@ -269,10 +270,13 @@ const driver = {
return res.databases; return res.databases;
}, },
async readCollection(pool, options) { async readCollection(pool, options) {
const mongoCondition = convertToMongoCondition(options.condition);
console.log('******************* mongoCondition *****************')
console.log(JSON.stringify(mongoCondition, undefined, 2));
try { try {
const collection = pool.__getDatabase().collection(options.pureName); const collection = pool.__getDatabase().collection(options.pureName);
if (options.countDocuments) { if (options.countDocuments) {
const count = await collection.countDocuments(convertObjectId(options.condition) || {}); const count = await collection.countDocuments(convertObjectId(mongoCondition) || {});
return { count }; return { count };
} else if (options.aggregate) { } else if (options.aggregate) {
let cursor = await collection.aggregate(convertObjectId(options.aggregate)); let cursor = await collection.aggregate(convertObjectId(options.aggregate));
@@ -280,7 +284,7 @@ const driver = {
return { rows: rows.map(transformMongoData) }; return { rows: rows.map(transformMongoData) };
} else { } else {
// console.log('options.condition', JSON.stringify(options.condition, undefined, 2)); // console.log('options.condition', JSON.stringify(options.condition, undefined, 2));
let cursor = await collection.find(convertObjectId(options.condition) || {}); let cursor = await collection.find(convertObjectId(mongoCondition) || {});
if (options.sort) cursor = cursor.sort(options.sort); if (options.sort) cursor = cursor.sort(options.sort);
if (options.skip) cursor = cursor.skip(options.skip); if (options.skip) cursor = cursor.skip(options.skip);
if (options.limit) cursor = cursor.limit(options.limit); if (options.limit) cursor = cursor.limit(options.limit);

View File

@@ -0,0 +1,99 @@
function convertLeftOperandToMongoColumn(left) {
if (left.exprType == 'placeholder') return '__placeholder__';
if (left.exprType == 'column') return left.columnName;
throw new Error(`Unknown left operand type ${left.exprType}`);
}
function convertRightOperandToMongoValue(right) {
if (right.exprType == 'value') return right.value;
throw new Error(`Unknown right operand type ${right.exprType}`);
}
function convertToMongoCondition(filter) {
if (!filter) {
return null;
}
switch (filter.conditionType) {
case 'and':
return {
$and: filter.conditions.map((x) => convertToMongoCondition(x)),
};
case 'or':
return {
$or: filter.conditions.map((x) => convertToMongoCondition(x)),
};
case 'binary':
switch (filter.operator) {
case '=':
return {
[convertLeftOperandToMongoColumn(filter.left)]: {
$eq: convertRightOperandToMongoValue(filter.right),
},
};
case '!=':
case '<>':
return {
[convertLeftOperandToMongoColumn(filter.left)]: {
$ne: convertRightOperandToMongoValue(filter.right),
},
};
case '<':
return {
[convertLeftOperandToMongoColumn(filter.left)]: {
$lt: convertRightOperandToMongoValue(filter.right),
},
};
case '<=':
return {
[convertLeftOperandToMongoColumn(filter.left)]: {
$lte: convertRightOperandToMongoValue(filter.right),
},
};
case '>':
return {
[convertLeftOperandToMongoColumn(filter.left)]: {
$gt: convertRightOperandToMongoValue(filter.right),
},
};
case '>=':
return {
[convertLeftOperandToMongoColumn(filter.left)]: {
$gte: convertRightOperandToMongoValue(filter.right),
},
};
}
break;
case 'isNull':
return {
[convertLeftOperandToMongoColumn(filter.expr)]: {
$exists: false,
},
};
case 'isNotNull':
return {
[convertLeftOperandToMongoColumn(filter.expr)]: {
$exists: true,
},
};
case 'not':
return {
$not: convertToMongoCondition(filter.condition),
};
case 'like':
return {
[convertLeftOperandToMongoColumn(filter.left)]: {
$regex: `${convertRightOperandToMongoValue(filter.right)}`.replace(/%/g, '.*'),
$options: 'i',
},
};
default:
throw new Error(`Unknown condition type ${filter.conditionType}`);
}
}
module.exports = {
convertToMongoCondition,
};