重复步骤中的克里姆林宫DSL使用错误

问题描述 投票:2回答:1

我们正在使用gremlin-javascript,并且最近开始定义DSL以简化查询。

[我不确定是否忽略了一些警告,但是当尝试在repeat步骤中使用DSL方法时,我始终收到(...).someDslFunction is not a function错误,但是在repeat之外使用相同的DSL功能可以正常工作。

这里是一个简短的(人为的)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

EDIT:感谢@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;

SOLUTION:以防万一其他人遇到这种情况。这就是我解决了将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;
javascript gremlin dsl tinkerpop3
1个回答
2
投票

我认为问题是因为您以__开始遍历,这是匿名遍历的标准TinkerPop生成。结果,您将创建一个GraphTraversal,而不是您的CustomDSLTraversalSource。 TinkerPop gremlin-javascript documentation指出:

在GraphTraversal上可用的步骤也应该作为匿名遍历的生成物可用

因此您可能应该拥有自己的返回__CustomDSLTraversalSource版本。如果您想更清楚地了解问题出在哪里,请参阅in the codecallOnEmptyTraversal()返回GraphTraversal,显然,您的DSL方法在该类上不可用。

© www.soinside.com 2019 - 2024. All rights reserved.