Last active
June 18, 2021 13:00
-
-
Save thomasdarimont/b54a8e9fcc01ed59d465 to your computer and use it in GitHub Desktop.
Simpler arithmetic expression syntax for MongoDB Aggregation Framework via AST Transformations
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
> expr("(a+b)*c") | |
{ "$multiply" : [ { "$add" : [ "$a", "$b" ] }, "$c" ] } | |
> expr("1+2*2+3") | |
{ | |
"$add" : [ | |
{ | |
"$add" : [ | |
1, | |
{ | |
"$multiply" : [ | |
2, | |
2 | |
] | |
} | |
] | |
}, | |
3 | |
] | |
} | |
> expr("-(1+2*2+3)") | |
{ | |
"$multiply" : [ | |
-1, | |
{ | |
"$add" : [ | |
{ | |
"$add" : [ | |
1, | |
{ | |
"$multiply" : [ | |
2, | |
2 | |
] | |
} | |
] | |
}, | |
3 | |
] | |
} | |
] | |
} | |
// use var args | |
> expr("(netPrice * _[0] + _[1]) * _[2]", 1.1 , 3.4, 1.19) | |
{ | |
"$multiply" : [ | |
{ | |
"$add" : [ | |
{ | |
"$multiply" : [ | |
"$netPrice", | |
1.1 | |
] | |
}, | |
3.4 | |
] | |
}, | |
1.19 | |
] | |
} | |
// use wrap arguments in array: | |
> expr("(netPrice * _[0] + _[1]) * _[2]", [1.1 , 3.4, 1.19]) | |
{ | |
"$multiply" : [ | |
{ | |
"$add" : [ | |
{ | |
"$multiply" : [ | |
"$netPrice", | |
1.1 | |
] | |
}, | |
3.4 | |
] | |
}, | |
1.19 | |
] | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
db.exprExample.insert({a:1,b:2,c:3}) | |
>db.exprExample.aggregate([{$project: {test: expr("a+b*c")}}]) | |
{ "_id" : ObjectId("53b51a0c5fac782ffc8dcfce"), "test" : 7 } | |
>db.exprExample.aggregate([{$project: {test: expr("(a+b)*c")}}]) | |
{ "_id" : ObjectId("53b51a0c5fac782ffc8dcfce"), "test" : 9 } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// http://jsep.from.so/ | |
load("/Users/tom/Documents/dev/repos/soney/jsep/build/jsep.js") | |
//Based on the work we did for: | |
//https://spring.io/blog/2013/12/04/what-s-new-in-spring-data-mongodb-1-4-m1 | |
function transformJsepExpression(node, args) { | |
var operators = {"+": "$add", "-": "$subtract", "*": "$multiply", "/": "$divide"}; | |
switch (node.type) { | |
case "BinaryExpression": | |
var part = {}; | |
part[operators[node.operator]] = [ transformJsepExpression(node.left, args), transformJsepExpression(node.right, args) ]; | |
return part; | |
case "Literal": | |
return node.value; | |
case "Identifier": | |
return "$" + node.name; | |
case "UnaryExpression": | |
if (node.operator == "-" && node.prefix) { | |
//if(node.argument.type == "Literal"){ | |
// we cannot simply return negative value since function result must be an object :( | |
// return -transformJsepExpression(node.argument); | |
//} | |
return {"$multiply": [-1, transformJsepExpression(node.argument, args)]}; | |
} else if (node.operator == "+") { | |
return transformJsepExpression(node.argument, args); | |
} | |
case "MemberExpression": | |
if (node.object | |
&& node.object.type == "Identifier" | |
&& node.object.name == "_" | |
&& args | |
&& typeof node.property.value == "number" | |
&& node.property.value < args.length) { | |
return args[node.property.value]; | |
} | |
} | |
return "error"; | |
}; | |
function expr(exprString, args) { | |
//treat first parameter as array or convert variable list of parameters to array and ignore first element (expression) | |
var argsList = typeof args == "object" ? args : Array.prototype.splice.call(arguments, 1, arguments.length - 1); | |
return transformJsepExpression(jsep(exprString), argsList); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment