【问题标题】:How to pass a complex lambda function to gremlin server by using Java API?如何使用 Java API 将复杂的 lambda 函数传递给 gremlin 服务器?
【发布时间】:2021-08-01 02:42:20
【问题描述】:

我正在尝试以间隔遍历图表。每条边都有一个存储间隔的属性(“间隔”)。我正在使用withSack 将区间的交叉点传播到下一步。如果没有交叉点,则遍历应该停止。

例如:

V1          e1         V2         e2          V3         e3          V4

O----------------------O----------------------O----------------------O
^
    [[1,3],[5,7]]              [[4,6]]                [[7,9]]
     e1.interval             e2.interval            e3.interval

如果我以区间 [2,8] 从 V1 开始遍历,我希望它返回

V1: [[2,3],[5,7]]
V2: [[5,6]]

注意 V3 和 V4 不包括在内,因为 e2 上的相交区间在 6 处停止。

我正在使用 Tinkerpop Java API,为此,我定义了一个返回区间交集的方法,并尝试使用withSack(Lambda.biFunction(...))。该函数有带花括号的while循环({}),我认为它会导致gremlin服务器的脚本引擎出现问题。我得到的例外是:

Script28.groovy: 1: expecting '}', found 'return' @ line 1, column 520.
   get(j).get(1)) i++; else j++;}return int

我将函数作为字符串传递给(Lambda.biFunction(...)),如下所示:

"x, y -> " +
"List<List<Long>> intersections = new ArrayList();" +
"if (x.isEmpty() || y.isEmpty()) return new ArrayList<>();" +
"int i = 0, j = 0;" +
"while (i < x.size() && j < y.size()) {" +
"long low = Math.max(x.get(i).get(0), y.get(j).get(0));" +
"long high = Math.min(x.get(i).get(1), y.get(j).get(1));" +
"if (low <= high) intersections.add(Arrays.asList(low, high));" +
"if (x.get(i).get(1) < y.get(j).get(1)) i++; else j++;" +
"}" +
"return intersections;";

为了可读性,我也放了原始函数:

public List<List<Long>> intersections(List<List<Long>> x, List<List<Long>> y) {
    List<List<Long>> intersections = new ArrayList();

    if (x.isEmpty() || y.isEmpty()) {
        return new ArrayList<>();
    }
    int i = 0, j = 0;

    while (i < x.size() && j < y.size()) {
        long low = Math.max(x.get(i).get(0), y.get(j).get(0));
        long high = Math.min(x.get(i).get(1), y.get(j).get(1));

        if (low <= high) {
            intersections.add(Arrays.asList(low, high));
        }

        if (x.get(i).get(1) < y.get(j).get(1)) {
            i++;
        } else {
            j++;
        }
    }

    return intersections;
}

我有两个问题:

  1. 如何将这样一个复杂的 lambda 函数传递给 gremlin 服务器?
  2. 有没有更好的方法来实现这一点?

【问题讨论】:

    标签: gremlin graph-databases tinkerpop tinkerpop3 gremlin-server


    【解决方案1】:

    您的 lambda 字符串需要匹配 Groovy closure form。对于您的多行和多参数脚本,您需要在其周围加上一些花括号:

    withSack(Lambda.biFunction(
    "{ x, y -> " +
    "  intersections = []\n" +
    "  if (x.isEmpty() || y.isEmpty()) return []\n" +
    "  i = 0\n" +
    "  j = 0\n" +
    "  while (i < x.size() && j < y.size()) {\n" +
    "    def low = Math.max(x[i][0], y[j][0])\n" +
    "    def high = Math.min(x[i][1], y[j][1])\n" +
    "    if (low <= high) intersections.add(Arrays.asList(low, high))\n" +
    "    if (x[i][1] < y[j][1]) i++; else j++\n" +
    "  }\n" +
    "  return intersections\n" +
    "}"))
    

    我还将您的 Java 转换为 Groovy(希望是正确的),这最终变得更加简洁,但那部分应该是不必要的。

    【讨论】:

    • 感谢您的回复。我得到了同样的例外:expecting '}', found 'if' @ line 1, column 158. x, y -&gt; intersections = [] if (x.isEm。但是,我已经将相同的函数写入了一个 groovy 脚本文件,该文件在服务器启动时由 ScriptFileGremlinPlugin 初始化。然后我就可以在我的查询中调用该函数了。
    • 哦...我去掉了分号,但没有添加换行符。更新的答案。也许这会解决它。这很简单。只是 groovy 评估中的语法错误。
    猜你喜欢
    • 2021-12-20
    • 2015-07-10
    • 1970-01-01
    • 1970-01-01
    • 2021-07-26
    • 2019-06-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多