“重复”步骤中的 Gremlin DSL 使用错误
Gremlin DSL usage errors within `repeat` step
我们正在使用 gremlin-javascript
并且最近开始定义 DSL 来简化我们的查询。
我不确定我是否忽略了一些注意事项,但是当尝试在 repeat
步骤中使用 DSL 方法时,我一直收到 (...).someDslFunction is not a function
错误,但在外部使用相同的 DSL 函数repeat
的工作没有问题。
这里是一个简短的(设计的)DSL 定义,它会产生这个问题:
class CustomDSLTraversal extends GraphTraversal {
constructor(graph, traversalStrategies, bytecode) {
super(graph, traversalStrategies, bytecode);
}
hasNotLabel(...args) {
return this.not(__.hasLabel(...args));
}
filterNotLabel(...args) {
return this.filter(__.hasNotLabel(...args));
}
}
class CustomDSLTraversalSource extends GraphTraversalSource {
constructor(graph, traversalStrategies, bytecode) {
super(graph, traversalStrategies, bytecode, CustomDSLTraversalSource, CustomDSLTraversal);
}
}
const statics = {
hasNotLabel: (...args) => callOnEmptyTraversal('hasNotLabel', args),
...gremlin.process.statics
};
const __ = statics;
const g = traversal(CustomDSLTraversalSource).withRemote(connection);
这里有两个用途,第一个没有问题,第二个导致 __.outE().(...).filterNotLabel is not a function
错误。
g.V('foo').outE().filterNotLabel('x', 'y').otherV(); // No errors
g.V('foo').repeat(__.outE().filterNotLabel('x', 'y').otherV()).times(1); // Error
// __.outE(...).filterNotLabel is not a function
编辑:感谢@stephen 指出现在如此明显的问题:
我重新定义了 callOnEmptyTraversal
以便与我们的 DSL 一起使用,并愚蠢地将标准的 TinkerPop 匿名遍历解构为我们的自定义遍历。这些显然是在调用原始的 callOnEmptyTraversal
,它确实使用了基础 GraphTraversal
.
的实例
function callOnEmptyTraversal(fn, args) {
const g = new CustomDSLTraversal(null, null, new Bytecode());
return g[fn].apply(g, args);
}
const statics = {
hasNotLabel: (...args) => callOnEmptyTraversal('hasNotLabel', args),
mapToObject: (...args) => callOnEmptyTraversal('mapToObject', args),
...gremlin.process.statics // Whoops
};
const __ = statics;
解决方案: 以防其他人遇到这种情况。这就是我如何解决将我们的 DSL 匿名遍历生成与标准 TinkerPop 生成合并的问题:
function callOnEmptyTraversal(fn, args) {
const g = new CustomDSLTraversal(null, null, new Bytecode());
return g[fn].apply(g, args);
}
function mapToCallOnEmptyTraversal(s, fn) {
s[fn] = (...args) => callOnEmptyTraversal(fn, args);
return s;
}
const statics = ['hasNotLabel', 'mapToObject']
.concat(Object.keys(gremlin.process.statics))
.reduce(mapToCallOnEmptyTraversal, {});
const __ = statics;
我认为问题是因为您使用 __
开始遍历,这是用于匿名遍历的标准 TinkerPop 生成。结果,您创建了 GraphTraversal
而不是 CustomDSLTraversalSource
。 TinkerPop gremlin-javascript documentation 指出:
steps that are made available on a GraphTraversal should also be made available as spawns for anonymous traversals
所以您可能应该有自己的 __
版本,即 returns 和 CustomDSLTraversalSource
。如果你想更明确地看到哪里出了问题,请参阅 in the code that callOnEmptyTraversal()
returns GraphTraversal
显然你的 DSL 方法在 class.
我们正在使用 gremlin-javascript
并且最近开始定义 DSL 来简化我们的查询。
我不确定我是否忽略了一些注意事项,但是当尝试在 repeat
步骤中使用 DSL 方法时,我一直收到 (...).someDslFunction is not a function
错误,但在外部使用相同的 DSL 函数repeat
的工作没有问题。
这里是一个简短的(设计的)DSL 定义,它会产生这个问题:
class CustomDSLTraversal extends GraphTraversal {
constructor(graph, traversalStrategies, bytecode) {
super(graph, traversalStrategies, bytecode);
}
hasNotLabel(...args) {
return this.not(__.hasLabel(...args));
}
filterNotLabel(...args) {
return this.filter(__.hasNotLabel(...args));
}
}
class CustomDSLTraversalSource extends GraphTraversalSource {
constructor(graph, traversalStrategies, bytecode) {
super(graph, traversalStrategies, bytecode, CustomDSLTraversalSource, CustomDSLTraversal);
}
}
const statics = {
hasNotLabel: (...args) => callOnEmptyTraversal('hasNotLabel', args),
...gremlin.process.statics
};
const __ = statics;
const g = traversal(CustomDSLTraversalSource).withRemote(connection);
这里有两个用途,第一个没有问题,第二个导致 __.outE().(...).filterNotLabel is not a function
错误。
g.V('foo').outE().filterNotLabel('x', 'y').otherV(); // No errors
g.V('foo').repeat(__.outE().filterNotLabel('x', 'y').otherV()).times(1); // Error
// __.outE(...).filterNotLabel is not a function
编辑:感谢@stephen 指出现在如此明显的问题:
我重新定义了 callOnEmptyTraversal
以便与我们的 DSL 一起使用,并愚蠢地将标准的 TinkerPop 匿名遍历解构为我们的自定义遍历。这些显然是在调用原始的 callOnEmptyTraversal
,它确实使用了基础 GraphTraversal
.
function callOnEmptyTraversal(fn, args) {
const g = new CustomDSLTraversal(null, null, new Bytecode());
return g[fn].apply(g, args);
}
const statics = {
hasNotLabel: (...args) => callOnEmptyTraversal('hasNotLabel', args),
mapToObject: (...args) => callOnEmptyTraversal('mapToObject', args),
...gremlin.process.statics // Whoops
};
const __ = statics;
解决方案: 以防其他人遇到这种情况。这就是我如何解决将我们的 DSL 匿名遍历生成与标准 TinkerPop 生成合并的问题:
function callOnEmptyTraversal(fn, args) {
const g = new CustomDSLTraversal(null, null, new Bytecode());
return g[fn].apply(g, args);
}
function mapToCallOnEmptyTraversal(s, fn) {
s[fn] = (...args) => callOnEmptyTraversal(fn, args);
return s;
}
const statics = ['hasNotLabel', 'mapToObject']
.concat(Object.keys(gremlin.process.statics))
.reduce(mapToCallOnEmptyTraversal, {});
const __ = statics;
我认为问题是因为您使用 __
开始遍历,这是用于匿名遍历的标准 TinkerPop 生成。结果,您创建了 GraphTraversal
而不是 CustomDSLTraversalSource
。 TinkerPop gremlin-javascript documentation 指出:
steps that are made available on a GraphTraversal should also be made available as spawns for anonymous traversals
所以您可能应该有自己的 __
版本,即 returns 和 CustomDSLTraversalSource
。如果你想更明确地看到哪里出了问题,请参阅 in the code that callOnEmptyTraversal()
returns GraphTraversal
显然你的 DSL 方法在 class.