Gremlin:图遍历语言

 

OLTP 和 OLAP遍历

  • 一遍编写,到处运行
    Gremlin听从“五次编写,到处运行”的计划性农学。这代表不但具备的TinkerPop启用的图形系统都能举办Gremlin遍历,而且每个Gremlin遍历都足以被评估为实时数据库查询或批处理查询。(前者被称之为在线交易流程(OLTP),后者被誉为在线分析流程(OLAP))。

  • 协调多种图遍历
    这种普遍性是由Gremlin遍历机实现的。这种分布式、基于图形的虚拟机了然怎么协调多机器图遍历的实施。好处是,用户不需要学习数据库查询语言和域特定的BigData分析语言(例如SparkDSL,MapReduce等)。Gremlin是构建基于图的应用程序所必需的,此外所有都交给Gremlin遍历机处理。
    葡京在线开户 1

``for``(Future<Integer> future : list) {

无缝嵌入主语言

  • 统一主开发语言和图查询语言
    经文数据库查询语言(如SQL)被认为与最后在生产环境中利用的编程语言截然不同。由此,经典数据库要求开发人员既要编写主编程语言,还要编写数据库相应的询问语言。Gremlin统一了那些划分,因为遍历可以用襄助成效结合和嵌套(首要编程语言都襄助)的别样编程语言编写。由此,用户的Gremlin遍历可以应用应用程序语言(主语言,Host
    language)编写,并受益于主语言及其工具(例如类型检查,语法高亮,点到位等)所提供的亮点。近期设有各类Gremlin语言变体,包括:Gremlin-Java,Gremlin-Groovy,Gremlin-Python,Gremlin-Scala等。

  • 演示程序
    正如之下两种办法,高低立判:

    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);
      }
    }
    

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遍历可以以命令式(程序式)模式,注解性(描述性)形式编写,也可以蕴涵命令性和表明性的搅和形式编写。

  • 命令式编写形式
    获取Gremlin合作者的顶头上司名字分布:

    g.V().has("name","gremlin").as("a").
      out("created").in("created").
    where(neq("a")).
      in("manages").
      groupCount().by("name")
    

    一个命令式的Gremlin遍历告诉运行器如何实施遍历中的每一步;然后,遍历器分裂到独具的“Gremlin”的合伙人(去除Gremlin自己);下一步,遍历器走到“Gremlin”合作者的顶头上司(managers),最终遵照上级的名字举行总括分发。

就此是命令式的Gremlin遍历,就是它明确地、程序化地告诉遍历器“去这里,然后去这边”。

  • 表明式编写形式
    以下使用表明式编写形式贯彻了一如既往的结果:

    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")
    

    表明式的Gremlin遍历并无法告诉遍历器执行它们的步调的次第,而是允许每个遍历器从一个(可能嵌套的)形式的集纳中采纳一个形式来施行。

但是,声明遍历具有额外的好处,它不但使用了编译时查询计划器(如命令式遍历),而且仍旧一个运转时查询计划器,遵照每个情势的野史总计信息选拔下一个实施哪个遍历形式

  • 便宜这多少个倾向于裁减/过滤大多数数目的形式。

用户可以选取上述提议的措施编写自己的遍历语句。不管咋样,用户的遍历语句都会遵照现实的履行引擎和遍历策略traversal
strategies
被重写。Gremlin为用户提供灵活性表明友好的查询的;图系统也本着现实启用TinkerPop的数据系统举办有效地评估图遍历提供了灵活性。

 

参考资料

The Gremlin Graph Traversal Machine and
Language

 

Gremlin简介

Gremlin是Apache TinkerPop
框架下的图遍历语言。Gremlin是一种函数式数据流语言,可以使得用户使用简单的主意表明复杂的习性图(property
graph)的遍历或询问。每个Gremlin遍历由一多样步骤(可能存在嵌套)组成,每一步都在数据流(data
stream)上实施一个原子操作。

Gremlin包括多个主导的操作:

  • map-step
    对数据流中的对象开展转换;
  • filter-step
    对数据流中的目的就行过滤;
  • sideEffect-step
    对数码流举行总结统计;

以下是Gremlin在局部场合中的具体应用:

  • 1.查找Gremlin朋友的朋友

    g.V().has("name","gremlin").
      out("knows").
      out("knows").
      values("name")
    
  • 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")
    
  • 3.提交Gremlin的兼具上司,直至首席执行官

    g.V().has("name","gremlin").
      repeat(in("manages")).
    until(has("title","ceo")).
      path().by("name")
    
  • 4.收获Gremlin合作者的职称分布

    g.V().has("name","gremlin").as("a").
      out("created").in("created").
    where(neq("a")).
      groupCount().by("title")
    
  • 葡京在线开户,5.获取Gremlin购买产品的连锁产品列表并排序

    g.V().has("name","gremlin").
      out("bought").aggregate("stash").
      in("bought").out("bought").
    where(not(within("stash"))).
      groupCount().order(local).by(values,decr)
    
  • 6.获取排行前十的为主人物

    g.V().hasLabel("person").
      pageRank().
    by("friendRank").
    by(outE("knows")).
      order().by("friendRank",decr).
      limit(10)
    

 

``sum += future.get();

 

 

 

 

``for``(``int i = ``0``; i < ``10``; i++) {

``System.out.println(sum);

 

import java.util.ArrayList;

 

 

三种办法都要经过重写run()方法来定义线程的所作所为,推荐应用后者,因为Java中的继承是单继承,一个类有一个父类,假诺连续了Thread类就无法再持续其他类了,显明使用Runnable接口更为灵活

``return sum;

 

``@Override

 

``// while(!future.isDone()) ;

import java.util.concurrent.Future;

 

``int sum = ``0``;

 

 

import java.util.concurrent.Callable;

``}

``this``.upperBounds = upperBounds;

import java.util.concurrent.Executors;

``ExecutorService service = Executors.newFixedThreadPool(``10``);

 

 

 

}

 

 

``}

 

 

 

``}

增补:Java
5将来创办线程还有第三种形式:实现Callable接口,该接口中的call方法可以在线程执行完毕时爆发一个重返值,代码如下所示:

 

``sum += i;

 

 

class Test {

 

 

``List<Future<Integer>> list = ``new ArrayList<>();

 

``for``(``int i = ``1``; i <= upperBounds; i++) {

 

 

 

}

Java
5从前实现多线程有三种实现格局:一种是延续Thread类;另一种是兑现Runnable接口。

 

``int sum = ``0``;

 

 

 

``}

 

import java.util.List;

 

 

 

``}

 

 

 

``public Integer call() ``throws Exception {

class MyTask ``implements Callable<Integer> {

 

``public static void main(String[] args) ``throws
Exception {

 

 

``private int upperBounds;

import java.util.concurrent.ExecutorService;

 

``public MyTask(``int upperBounds) {

 

``}

 

 

``list.add(service.submit(``new
MyTask((``int``) (Math.random() * ``100``))));