Node js中的复杂recursion

我需要帮助试图通过这个JSON对象recursion来build立一个查询。 我正在JavaScript中这样做。

的NodeJS

我有一个像这样的对象

{ type: "and", left: { type: "eq", left: { type: "property", name: "City" }, right: { type: "literal", value: "Seattle" } }, right: { type: "and", left: { type: "eq", left: { type: "property", name: "State" }, right: { type: "literal", value: "Washington" } }, right: { type: "and", left: { type: "eq", left: { type: "property", name: "FirstName" }, right: { type: "literal", value: "John" } }, right: { type: "eq", left: { type: "property", name: "LastName" }, right: { type: "literal", value: "Doe" } } } } }; 

这是一些代码。 上面的对象将作为querySchema传入下面的过滤方法。

我一直在尝试许多不同的食谱来完成这个任务。 这与我所做的任何recursion不同。

 var QueryBuilder = Class({ constructor: function (model) { this.model = new model(); }, filter: function (querySchema) { var self = this; // recurse somewhere in here and run the conditions below somewhere in the midst // of the recursion. if (querySchema.hasOwnProperty(property)) { if (property == 'type' && querySchema[property] == 'and') { self.filter(querySchema.left); } if (querySchema.type == 'eq') { this.model.where(querySchema.left.name).equals(querySchema.right.); } if (querySchema.type == 'gt') { this.model.where(querySchema.left.name).gt(querySchema['right']); } if (querySchema.type == 'lt') { this.model.where(querySchema.left.name).lt(querySchema['right']); } } } }); 

很感谢任何forms的帮助。

 { type: "eq", left: { type: "property", name: "State" }, right: { type: "literal", value: "Washington" } } 

当你只能比较属性和字面值时,你不应该在这里使用rightleft (这表示任何types的树)。

 { type: "and", left: …, right: { type: "and", left: …, right: { type: "and", left: …, right: … } } }; 

如果只能表示子句的连接 ,请使用数组。 看起来你的模型不支持比这更多的东西,它会使你的filter方法变得更容易(你不需要使用recursion)。

你似乎不打算改变格式,但是当我的上述假设是正确的,那么这应该就足够了:

 filter: function (querySchema) { if (querySchema.type == 'and') { // standard binary tree traversal recursion: this.filter(querySchema.left); this.filter(querySchema.right); } else if (querySchema.type == 'eq') { this.model.where(querySchema.left.name).equals(querySchema.right.value); } else if (querySchema.type == 'gt') { this.model.where(querySchema.left.name).gt(querySchema.right.value); } else if (querySchema.type == 'lt') { this.model.where(querySchema.left.name).lt(querySchema.right.value); } } 

更健壮的版本(不改变recursion,但是)将是:

 filter: function (querySchema) { var t = querySchema.type, l = querySchema.left, r = querySchema.right; if (t == 'and') { this.filter(l); this.filter(r); } else if (t == 'eq' || t == 'gt' || == 'lt') { if (l.type != "property" || r.type != "literal") throw new SyntaxError("Invalid comparison in query schema"); this.model.where(l.name)[t=='eq'?'equals':t](r.value); } else throw new SyntaxError("Unknown type in query schema") } 

这是一个答案,它将采取你的树,并使用recursion来返回结果。

码:

 #!/usr/bin/env node var util = require('util'); util.puts("Convert tree to query!"); var tree = { /* your tree object */ }; var readNode = function(node) { if (node.type === "eq") { return "(" + node.left.name + " = '" + node.right.value + "')"; } if (node.type === "and") { return readNode(node.left) + " and " + readNode(node.right); } }; util.puts(readNode(tree)); 

输出:

 (City = 'Seattle') and (State = 'Washington') and (FirstName = 'John') and (LastName = 'Doe')