我需要帮助尝试通过此JSON对象进行递归来构建查询。我是用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传递给下面的过滤方法。
我一直在尝试许多不同的食谱来完成这项工作。这与我曾经做过的任何递归不同。
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']);
}
}
}
});
非常感谢任何帮助。
答案 0 :(得分:1)
{ type: "eq", left: { type: "property", name: "State" }, right: { type: "literal", value: "Washington" } }
当您只能将属性与文字值进行比较时,不应在此使用right
和left
(这表示任何类型的树)。
{ type: "and", left: …, right: { type: "and", left: …, right: { type: "and", left: …, right: … } } };
如果只能代表conjunction条款,请使用数组。看起来你的模型不支持更多,它会使你的filter
方法更容易(你不需要使用递归)。
您似乎不打算更改格式,但是当我的上述假设正确时,这应该足够了:
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);
}
}
更强大的版本(不改变递归)将是:
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")
}
答案 1 :(得分:0)
这是一个回答,它采用树并使用递归来返回结果。
#!/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')