本博文为翻译自官网的博文,官网:http://tinkerpop.apache.org/gremlin.html
Gremlin是Apache TinkerPop 框架下的图遍历语言,而TinkerPop是JanusGraph的搜索引擎。Gremlin是一种函数式数据流语言,可以使得用户使用简洁的方式表述复杂的属性图(property graph)的遍历或查询。
每个Gremlin遍历由一系列步骤(可能存在嵌套)组成,每一步都在数据流(data stream)上执行一个原子操作。每个步骤都是map -step(转换流中的对象),filter -step(从流中删除对象)或sideEffect-step(计算有关流的统计信息)。Gremlin操作库扩展了这些3基本操作,为用户提供了丰富的step,用户可以编写这些step,以便更加灵活的获取所需要的数据。
1:获取Gremlin的朋友的朋友的名字
g.V().has("name","gremlin").
out("knows").
out("knows").
values("name")
步骤:1. 获取名为“gremlin”的顶点。
2. 得到gremlin知道的人。
3. 遍历那些人都知道的人。
4. 得到那些人的名字。
2:被两位是朋友关系的人创建的项目名称
g.V().match(
as("a").out("knows").as("b"),
as("a").out("created").as("c"),
as("b").out("created").as("c"),
as("c").in("created").count().is(2)).
select("c").by("name")
步骤:1. 创建匹配规则:存在a与b的认识关系。
2. 存在a创造了c。
3. 存在b创造了c。
4. 存在c被创建的关系的个数为2。
5. 根据匹配规则,获取所有匹配的“c”项目的名称。
3:获取gremlin用户的所有管理者的名字直到ceo
g.V().has("name","gremlin").
repeat(in("manages")).
until(has("title","ceo")).
path().by("name")
步骤:1.找到gremlin节点
2.遍历查找gremlin的被管理关系
3.直到查找到的节点包含title为ceo的节点为止
4.在遍历路径中的管理者姓名
4:获取gremlin用户的不同领域的合作者的title和其数量
g.V().has("name","gremlin").as("a").
out("created").in("created").
where(neq("a")).
groupCount().by("title")
步骤:1.获取gremlin用户顶点并将该顶点设置为a,则下面的a便代表gremlin这个顶点
2.找到gremlin创造的项目,并且创建这些项目的人。得到的结果就是a和a的合作者
3.去除a,只剩下的a的合作者
4.通过title进行聚合计数,获得最终结果
5:获取gremlin购买的相关产品的的排名列表
g.V().has("name","gremlin").
out("bought").aggregate("stash").
in("bought").out("bought").
where(not(within("stash")))。
order().by("friendRank",desc).
groupCount().order(local).by(values,desc)
步骤:1. 获取名为“gremlin”的顶点
2. 获取Gremlin购买的产品并保存为以“stash”命名的临时集合
3. 还有谁买了这些产品,并且得到他们买的东西
4. 对结果集去除Gremlin购买的
5. 按照分组的结果进行降序排序
6:在知识图中获取10个最核心的人
g.V().hasLabel("person").
pageRank().
by("friendRank").
by(outE("knows")).
order().by("friendRank",desc).
limit(10)
步骤:1. 获取所有”人“的顶点
2. 使用know-edges计算他们的PageRank。
3. 通过他们的朋友排名得分。
4. 获得排名前10位的人。
//pageRank()是google发明的页面排名算法,要想使用,必须这样创建g = graph.traversal().withComputer()
Gremlin遵循“一次编写,到处运行”的设计哲学。这意味着不仅所有的TinkerPop启用的图形系统都能执行Gremlin遍历,而且每个Gremlin遍历都可以被评估为实时数据库查询或批处理查询。前者被称为在线交易流程(OLTP),后者被称为在线分析流程(OLAP)。
这主要得益于Gremlin traversal machine(Gremlin遍历机)。这种分布式、基于图形的虚拟机了解如何协调多机器图遍历的执行。这样做的好处是用户不需要学习数据库查询语言和域特定的BigData分析语言(例如Spark DSL,MapReduce等)。Gremlin是构建基于图的应用程序所必要的,其余一切都交给Gremlin遍历机处理。
Gremlin遍历可以以命令式(程序式)方式,声明性(描述性)方式编写,也可以包含命令性和声明性的混合方式编写。
命令式的Gremlin遍历告诉遍历者如何在遍历中的每一步进行。
例如,下面的命令遍历首先将遍历器放置在表示Gremlin的顶点处。 然后那个将自己分裂到Gremlin的所有合作者身上,而这些合作者并不是Gremlin本人。 接下来,遍历者获取这些协作者的管理者,最终被分组为经理姓名计数分布。
这种遍历以明确的程序方式告诉遍历者“去这里然后去那里”。
g.V().has("name","gremlin").as("a").
out("created").in("created").
where(neq("a")).
in("manages").
groupCount().by("name")
声明式Gremlin遍历并不告诉遍历者执行其遍历的顺序,而是允许每个遍历器从一组(可能嵌套的)模式中选择要执行的模式。
下面的声明式遍历产生与上面的命令式遍历相同的结果。
但是,声明式遍历还有一个额外的好处,即它不仅利用编译时查询计划程序(如命令式遍历),而且还利用运行时查询计划程序,根据每个模式的历史统计信息选择接下来要执行的遍历模式 - 支持那些倾向于 reduce/filter大多数数据的模式。
g.V().match(
as("a").has("name","gremlin"),
as("a").out("created").as("b"),
as("b").in("created").as("c"),
as("c").in("manages").as("d"),
where("a",neq("c"))).
select("d").
groupCount().by("name")
用户可以选择的以任何方式编写遍历。当语句被编译时,取决于底层执行引擎(即OLTP图形数据库或OLAP图形处理器),用户的遍历由一组遍历策略重写,这些策略尽最大努力基于对图数据访问成本的理解以及底层数据系统的独特功能(例如,从图数据库的“名称” - 索引中获取Gremlin顶点)确定最佳执行计划 。Gremlin旨在为用户提供表达查询的灵活性,并为系统提供者提供如何有效评估针对其启用TinkerPop的数据系统的遍历的灵活性。
经典数据库查询语言(如SQL)被认为与最终在生产环境中使用它们的编程语言有根本的不同。出于这个原因,经典数据库要求开发人员以其本机编程语言以及数据库的相应查询语言进行编码。“查询语言”和“编程语言”之间的差异并不像我们所教导的那么大。
Gremlin统一了这种鸿沟,遍历可以用任何支持函数组合和嵌套的编程语言编写(每种主要的编程语言都支持)。通过这种方式,用户的Gremlin遍历与其应用程序代码一起编写,并受益于宿主语言及其工具提供的优势(例如,类型检查,语法突出显示等)。存在各种Gremlin语言变体,包括:Gremlin-Java,Gremlin-Groovy,Gremlin-Python, Gremlin-Scala等。
下面的第一个示例显示了一个简单的Java类。请注意,Gremlin遍历以Gremlin-Java表示,因此是用户应用程序代码的一部分。遍历嵌入在用户的主机编程语言中,并与所有其他应用程序代码平等。
public class GremlinTinkerPopExample {
public void run(String name, String property) {
Graph graph = GraphFactory.open(...);
GraphTraversalSource g = graph.traversal();
double avg = g.V().has("name",name).
out("knows").out("created").
values(property).mean().next();
System.out.println("Average rating: " + avg);
}}
使用Gremlin,用户不必处理下面第二个例子中举例说明的尴尬,这是整个行业中常见的反模式。
public class SqlJdbcExample {
public void run(String name, String property) {
Connection connection = DriverManager.getConnection(...)
Statement statement = connection.createStatement();
ResultSet result = statement.executeQuery(
"SELECT AVG(pr." + property + ") as AVERAGE FROM PERSONS p1" +
"INNER JOIN KNOWS k ON k.person1 = p1.id " +
"INNER JOIN PERSONS p2 ON p2.id = k.person2 " +
"INNER JOIN CREATED c ON c.person = p2.id " +
"INNER JOIN PROJECTS pr ON pr.id = c.project " +
"WHERE p.name = '" + name + "');
System.out.println("Average rating: " + result.next().getDouble("AVERAGE")
}}
在底层,Gremlin遍历将针对嵌入式图形数据库进行本地评估,通过网络将自身序列化为远程图形数据库,或将自身发送到OLAP处理器以进行集群范围的分布式执行。遍历源定义确定遍历执行的位置,一旦定义了遍历源,就可以以类似于数据库连接的方式反复使用它。最终的效果是用户“感觉”他们的数据和遍历都位于他们的应用程序中,并且可以通过他们的应用程序的本机编程语言访问。“查询语言/编程语言”-divide由Gremlin桥接。
想要知道gremlin更多的用法,官网demo地址(特别详细):http://kelvinlawrence.net/book/Gremlin-Graph-Guide.html#tpintro