总的来说,Gremlin 是一种图查询的DSL语言,在tinkerpop的实现中;他采用了 groovy 脚本来支持;
大家可以先看看这篇文章;
https://blog.csdn.net/dnc8371/article/details/106705467
其实tinkerpop-gremlin的实现思路与其基本一致,首先是用 java 语言构建了 方法链式的 dsl调用
Graph().edge()
.from("a")
.to("b")
.weight(40.0)
.edge()
.from("b")
.to("c")
.weight(20.0)
.edge()
.from("d")
.to("e")
.weight(50.5)
.printGraph();
这个java风格的代码和我们使用gremlin查询语句的风格是不是非常的像?
从链接文章的思路我们可以看到, 方法链的模式,是非常依赖builder 模式来构建查询语句的;
在有了java 模型之后,又是如何映射到 具体gremlin 语句上的呢?
我们第一感觉就是,把这个java 语句变成字符串,让java 动态执行不就可以了吗。
整个实现的思路其实就是这样的,动态执行 一段 语言脚本。 只不过 tinkerpop 使用的是groovy 脚本;
非常灵活,且和java 兼容;
Binding binding = new Binding();
Graph g = new Graph();
binding.setVariable("g", Graph());
binding.setVariable("language", "Groovy");
GroovyShell shell = new GroovyShell(binding);
Object value = shell.evaluate("g.edge()\n" +
" .from(\"a\")\n" +
" .to(\"b\")\n" +
" .weight(40.0)\n" +
" .edge()\n" +
" .from(\"b\")\n" +
" .to(\"c\")\n" +
" .weight(20.0)\n" +
" .edge()\n" +
" .from(\"d\")\n" +
" .to(\"e\")\n" +
" .weight(50.5)\n" +
" .printGraph();");
System.out.println(value);
上述的代码,就是把绑定了 一个变量 g = Graph(); 然后执行整个 查询; 可以看到效果基本和gremlin 一模一样;
依赖的就是GroovyShell 的执行引擎; 其实 整个 shell 还可以是从文件中加载, 也可以定义大量的其他变量;
知道了原理之后,我们其实可以在gremlin 查询里面 完成非常复杂的事情,只要是 groovy 支持的,都可以支持,
这样就可以实现特别复杂的执行计划;
另外,如果我们想要扩展gremlin 的函数,那么我们需要在java模型里添加相应的功能;
更深层次的问题, groovyShell 是如何 解析 groovy 语言的呢? 那就要回到 编译原理的词法 语法分析上去了;
我们最近接到的一个需求是 上游 使用论文中定义的某种 查询DSL,需要转化成 gremlin; 那么我们也不得不使用一些编译原理的工具比如 antlr 来自定义 DSL 解析和使用; 这部分涉及到原理性的东西,后续更新;
网友评论