Gremlin-Console

Gremlin-Console 是由 Tinkerpop 自己开发的一个交互式客户端,用户可以使用该客户端对 Graph 做各种操作,主要有两种使用模式:

  • 单机离线调用模式
  • Client/Server 请求模式

1 单机离线调用模式

由于 lib 目录下已经包含了 HugeCore 的 jar 包,且 HugeGraph 已经作为插件注册到 Console 中,用户可以直接写 groovy 脚本调用 HugeGraph-Core 的代码,然后交由 Gremlin-Console 内的解析引擎执行,就能在不启动 Server 的情况下操作图。

这种模式便于用户快速上手体验,但是不适合大量数据插入和查询的场景。下面给一个示例:

在 script 目录下有一个示例脚本 example.groovy

  1. import org.apache.hugegraph.HugeFactory
  2. import org.apache.hugegraph.backend.id.IdGenerator
  3. import org.apache.hugegraph.dist.RegisterUtil
  4. import org.apache.hugegraph.type.define.NodeRole
  5. import org.apache.tinkerpop.gremlin.structure.T
  6. RegisterUtil.registerRocksDB()
  7. conf = "conf/graphs/hugegraph.properties"
  8. graph = HugeFactory.open(conf)
  9. graph.serverStarted(IdGenerator.of("server-tinkerpop"), NodeRole.MASTER)
  10. schema = graph.schema()
  11. schema.propertyKey("name").asText().ifNotExist().create()
  12. schema.propertyKey("age").asInt().ifNotExist().create()
  13. schema.propertyKey("city").asText().ifNotExist().create()
  14. schema.propertyKey("weight").asDouble().ifNotExist().create()
  15. schema.propertyKey("lang").asText().ifNotExist().create()
  16. schema.propertyKey("date").asText().ifNotExist().create()
  17. schema.propertyKey("price").asInt().ifNotExist().create()
  18. schema.vertexLabel("person").properties("name", "age", "city").primaryKeys("name").ifNotExist().create()
  19. schema.vertexLabel("software").properties("name", "lang", "price").primaryKeys("name").ifNotExist().create()
  20. schema.indexLabel("personByCity").onV("person").by("city").secondary().ifNotExist().create()
  21. schema.indexLabel("personByAgeAndCity").onV("person").by("age", "city").secondary().ifNotExist().create()
  22. schema.indexLabel("softwareByPrice").onV("software").by("price").range().ifNotExist().create()
  23. schema.edgeLabel("knows").sourceLabel("person").targetLabel("person").properties("date", "weight").ifNotExist().create()
  24. schema.edgeLabel("created").sourceLabel("person").targetLabel("software").properties("date", "weight").ifNotExist().create()
  25. schema.indexLabel("createdByDate").onE("created").by("date").secondary().ifNotExist().create()
  26. schema.indexLabel("createdByWeight").onE("created").by("weight").range().ifNotExist().create()
  27. schema.indexLabel("knowsByWeight").onE("knows").by("weight").range().ifNotExist().create()
  28. marko = graph.addVertex(T.label, "person", "name", "marko", "age", 29, "city", "Beijing")
  29. vadas = graph.addVertex(T.label, "person", "name", "vadas", "age", 27, "city", "Hongkong")
  30. lop = graph.addVertex(T.label, "software", "name", "lop", "lang", "java", "price", 328)
  31. josh = graph.addVertex(T.label, "person", "name", "josh", "age", 32, "city", "Beijing")
  32. ripple = graph.addVertex(T.label, "software", "name", "ripple", "lang", "java", "price", 199)
  33. peter = graph.addVertex(T.label, "person", "name", "peter", "age", 35, "city", "Shanghai")
  34. marko.addEdge("knows", vadas, "date", "20160110", "weight", 0.5)
  35. marko.addEdge("knows", josh, "date", "20130220", "weight", 1.0)
  36. marko.addEdge("created", lop, "date", "20171210", "weight", 0.4)
  37. josh.addEdge("created", lop, "date", "20091111", "weight", 0.4)
  38. josh.addEdge("created", ripple, "date", "20171210", "weight", 1.0)
  39. peter.addEdge("created", lop, "date", "20170324", "weight", 0.2)
  40. graph.tx().commit()
  41. g = graph.traversal()
  42. System.out.println(">>>> query all vertices: size=" + g.V().toList().size())
  43. System.out.println(">>>> query all edges: size=" + g.E().toList().size())

其实这一段 groovy 脚本几乎就是 Java 代码,不同之处仅在于变量的定义可以不写类型声明,以及每一行末尾的分号可以去掉。

g.V() 是获取所有的顶点,g.E() 是获取所有的边,toList() 是把结果存到一个 List 中,参考 TinkerPop Terminal Steps

下面进入 gremlin-console,并传入该脚本令其执行:

  1. > ./bin/gremlin-console.sh -- -i scripts/example.groovy
  2. \,,,/
  3. (o o)
  4. -----oOOo-(3)-oOOo-----
  5. plugin activated: HugeGraph
  6. plugin activated: tinkerpop.server
  7. plugin activated: tinkerpop.utilities
  8. plugin activated: tinkerpop.tinkergraph
  9. main dict load finished, time elapsed 644 ms
  10. model load finished, time elapsed 35 ms.
  11. >>>> query all vertices: size=6
  12. >>>> query all edges: size=6
  13. gremlin>

这里的 -- 会被 getopts 解析为最后一个 option,这样后面的 options 就可以传入 Gremlin-Console 进行处理了。-i 代表 Execute the specified script and leave the console open on completion,更多的选项可以参考 Gremlin-Console 的源代码

可以看到,插入了 6 个顶点、6 条边,并查询出来了。进入 console 之后,还可继续输入 groovy 语句对图做操作:

  1. gremlin> g.V()
  2. ==>v[2:lop]
  3. ==>v[1:josh]
  4. ==>v[1:marko]
  5. ==>v[1:peter]
  6. ==>v[1:vadas]
  7. ==>v[2:ripple]
  8. gremlin> g.E()
  9. ==>e[S1:josh>2>>S2:lop][1:josh-created->2:lop]
  10. ==>e[S1:josh>2>>S2:ripple][1:josh-created->2:ripple]
  11. ==>e[S1:marko>1>>S1:josh][1:marko-knows->1:josh]
  12. ==>e[S1:marko>1>>S1:vadas][1:marko-knows->1:vadas]
  13. ==>e[S1:marko>2>>S2:lop][1:marko-created->2:lop]
  14. ==>e[S1:peter>2>>S2:lop][1:peter-created->2:lop]
  15. gremlin>

更多的 Gremlin 语句请参考 Tinkerpop 官网

2 Client/Server 请求模式

因为 Gremlin-Console 只能通过 WebSocket 连接 HugeGraph-Server,默认 HugeGraph-Server 是对外提供 HTTP 连接的,所以先修改 gremlin-server 的配置。

注意:将连接方式修改为 WebSocket 后,HugeGraph-Client、HugeGraph-Loader、HugeGraph-Hubble 等配套工具都不能使用了。

  1. # vim conf/gremlin-server.yaml
  2. # ......
  3. # If you want to start gremlin-server for gremlin-console (web-socket),
  4. # please change `HttpChannelizer` to `WebSocketChannelizer` or comment this line.
  5. channelizer: org.apache.tinkerpop.gremlin.server.channel.HttpChannelizer
  6. # ......

channelizer: org.apache.tinkerpop.gremlin.server.channel.HttpChannelizer 修改成 channelizer: org.apache.tinkerpop.gremlin.server.channel.WebSocketChannelizer 或直接注释,然后按照步骤启动 HugegraphServer。

下面进入 gremlin-console:

  1. > ./bin/gremlin-console.sh
  2. \,,,/
  3. (o o)
  4. -----oOOo-(3)-oOOo-----
  5. plugin activated: HugeGraph
  6. plugin activated: tinkerpop.server
  7. plugin activated: tinkerpop.utilities
  8. plugin activated: tinkerpop.tinkergraph

连接 server,需在配置文件中指定连接参数,在 conf 目录下有一个默认的 remote.yaml

  1. # cat conf/remote.yaml
  2. hosts: [localhost]
  3. port: 8182
  4. serializer: {
  5. className: org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV1d0,
  6. config: {
  7. serializeResultToString: false,
  8. ioRegistries: [org.apache.hugegraph.io.HugeGraphIoRegistry]
  9. }
  10. }
  1. gremlin> :remote connect tinkerpop.server conf/remote.yaml
  2. ==>Configured localhost/127.0.0.1:8182

连接成功之后,如果在启动 HugeGraphServer 的过程中导入了示例图 example.groovy,就可以在 console 中直接进行查询

  1. gremlin> :> hugegraph.traversal().V()
  2. ==>[id:2:lop,label:software,type:vertex,properties:[name:lop,lang:java,price:328]]
  3. ==>[id:1:josh,label:person,type:vertex,properties:[name:josh,age:32,city:Beijing]]
  4. ==>[id:1:marko,label:person,type:vertex,properties:[name:marko,age:29,city:Beijing]]
  5. ==>[id:1:peter,label:person,type:vertex,properties:[name:peter,age:35,city:Shanghai]]
  6. ==>[id:1:vadas,label:person,type:vertex,properties:[name:vadas,age:27,city:Hongkong]]
  7. ==>[id:2:ripple,label:software,type:vertex,properties:[name:ripple,lang:java,price:199]]

注意:在 Client/Server 模式下,所有和 Server 有关的操作都要加上 :> ,如果不加,表示在 console 本地操作。

还可以把多条语句放在一个字符串变量中,然后一次性发给 Server:

  1. gremlin> script = """
  2. ......1> graph = hugegraph;
  3. ......2> g = graph.traversal();
  4. ......3> g.V().toList().size();
  5. ......4> """
  6. ==>
  7. graph = hugegraph;
  8. g = graph.traversal();
  9. g.V().toList().size();
  10. gremlin> :> @script
  11. ==>6
  12. gremlin>

更多关于 gremlin-console 的使用,请参考 Tinkerpop 官网

Last modified June 12, 2023: doc: update Log4j2 configuration and gremlin-console guide (#268) (46ee92e3)