Javascript 节点js中的复杂递归

Javascript 节点js中的复杂递归,javascript,node.js,recursion,Javascript,Node.js,Recursion,我需要帮助尝试通过这个JSON对象递归来构建查询。我是用JavaScript实现的 NodeJS 我有一个像这样的物体 { type: "and", left: { type: "eq", left: { type: "property", name: "City" }, right: { type: "literal",

我需要帮助尝试通过这个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传递到下面的filter方法中

我一直在尝试许多不同的食谱来达到这个目的。这与我做过的任何递归都不同

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']);
      }
    }
  }
});
非常感谢您的帮助

当只能将属性与文字值进行比较时,不应在此处使用
right
left
(这表示任何类型的树)

如果只能表示一组子句,请使用数组。您的模型似乎不支持比这更多的功能,而且它将使您的
过滤器
方法更容易(您不需要使用递归)

您似乎不打算更改格式,但当我的上述假设正确时,这就足够了:

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")
}

下面是一个答案,它采用您的树并使用递归返回结果

代码: 输出:
欢迎来到这个网站!如果你解释清楚为什么你需要帮助,你会得到更好的答案。什么不起作用?您是否收到错误消息?如果是,它们是什么?发生了什么,您期望发生什么,它们有什么不同(如果不明显的话)?什么是
,什么是
模型
,哪些
方法在哪里?如何将属性相互比较,还有其他类型吗?json的模式是什么?类只是创建原型继承和简单的基于类的语法的简单方法。阶级和模式不重要。目标是递归上面对象中的值并构建查询。is对象是根据查询字符串生成的@user3254599:好的,我发现您不能真正更改输出。但是,您想如何构建查询?我想您不是指查询字符串吧?请解释您希望代码做什么。这是一个有趣的模型。是否允许
类型:'或'
?然后你要确保你正确地处理它。很好的挑战。我们差不多同时回答。我测试了您的代码(将输出更改为字符串),结果成功了。和我的基本算法一样+1它似乎无法处理
lt
gt
类型。顺便说一句,因为OP在评论中说他从解析器那里得到了语法树,我想他不想把它转换回字符串:-)
lt
gt
都是琐碎的事情。我没有可以使用的模型,所以字符串输出显示了代码需要如何编写。
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")
}
#!/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')