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 com.baidu.hugegraph.HugeFactory
  2. import com.baidu.hugegraph.dist.RegisterUtil
  3. import org.apache.tinkerpop.gremlin.structure.T
  4. RegisterUtil.registerCassandra();
  5. RegisterUtil.registerScyllaDB();
  6. conf = "conf/hugegraph.properties"
  7. graph = HugeFactory.open(conf);
  8. schema = graph.schema();
  9. schema.propertyKey("name").asText().ifNotExist().create();
  10. schema.propertyKey("age").asInt().ifNotExist().create();
  11. schema.propertyKey("city").asText().ifNotExist().create();
  12. schema.propertyKey("weight").asDouble().ifNotExist().create();
  13. schema.propertyKey("lang").asText().ifNotExist().create();
  14. schema.propertyKey("date").asText().ifNotExist().create();
  15. schema.propertyKey("price").asInt().ifNotExist().create();
  16. schema.vertexLabel("person").properties("name", "age", "city").primaryKeys("name").ifNotExist().create();
  17. schema.vertexLabel("software").properties("name", "lang", "price").primaryKeys("name").ifNotExist().create();
  18. schema.indexLabel("personByName").onV("person").by("name").secondary().ifNotExist().create();
  19. schema.indexLabel("personByCity").onV("person").by("city").secondary().ifNotExist().create();
  20. schema.indexLabel("personByAgeAndCity").onV("person").by("age", "city").secondary().ifNotExist().create();
  21. schema.indexLabel("softwareByPrice").onV("software").by("price").range().ifNotExist().create();
  22. schema.edgeLabel("knows").sourceLabel("person").targetLabel("person").properties("date", "weight").ifNotExist().create();
  23. schema.edgeLabel("created").sourceLabel("person").targetLabel("software").properties("date", "weight").ifNotExist().create();
  24. schema.indexLabel("createdByDate").onE("created").by("date").secondary().ifNotExist().create();
  25. schema.indexLabel("createdByWeight").onE("created").by("weight").range().ifNotExist().create();
  26. schema.indexLabel("knowsByWeight").onE("knows").by("weight").range().ifNotExist().create();
  27. marko = graph.addVertex(T.label, "person", "name", "marko", "age", 29, "city", "Beijing");
  28. vadas = graph.addVertex(T.label, "person", "name", "vadas", "age", 27, "city", "Hongkong");
  29. lop = graph.addVertex(T.label, "software", "name", "lop", "lang", "java", "price", 328);
  30. josh = graph.addVertex(T.label, "person", "name", "josh", "age", 32, "city", "Beijing");
  31. ripple = graph.addVertex(T.label, "software", "name", "ripple", "lang", "java", "price", 199);
  32. peter = graph.addVertex(T.label, "person", "name", "peter", "age", 35, "city", "Shanghai");
  33. marko.addEdge("knows", vadas, "date", "20160110", "weight", 0.5);
  34. marko.addEdge("knows", josh, "date", "20130220", "weight", 1.0);
  35. marko.addEdge("created", lop, "date", "20171210", "weight", 0.4);
  36. josh.addEdge("created", lop, "date", "20091111", "weight", 0.4);
  37. josh.addEdge("created", ripple, "date", "20171210", "weight", 1.0);
  38. peter.addEdge("created", lop, "date", "20170324", "weight", 0.2);
  39. graph.tx().commit();
  40. g = graph.traversal();
  41. System.out.println(">>>> query all vertices: size=" + g.V().toList().size());
  42. 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 scripts/example.groovy
  2. objc[5038]: Class JavaLaunchHelper is implemented in both /Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/bin/java (0x10137a4c0) and /Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/jre/lib/libinstrument.dylib (0x102bbb4e0). One of the two will be used. Which one is undefined.
  3. \,,,/
  4. (o o)
  5. -----oOOo-(3)-oOOo-----
  6. plugin activated: com.baidu.hugegraph
  7. plugin activated: tinkerpop.server
  8. plugin activated: tinkerpop.utilities
  9. plugin activated: tinkerpop.tinkergraph
  10. 2018-01-15 14:36:19 7516 [main] [WARN ] com.baidu.hugegraph.config.HugeConfig [] - The config option 'rocksdb.data_path' is redundant, please ensure it has been registered
  11. 2018-01-15 14:36:19 7523 [main] [WARN ] com.baidu.hugegraph.config.HugeConfig [] - The config option 'rocksdb.wal_path' is redundant, please ensure it has been registered
  12. 2018-01-15 14:36:19 7604 [main] [INFO ] com.baidu.hugegraph.HugeGraph [] - Opening backend store 'cassandra' for graph 'hugegraph'
  13. >>>> query all vertices: size=6
  14. >>>> query all edges: size=6

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

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

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

2 Client/Server请求模式

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

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

  1. # vim conf/gremlin-server.yaml
  2. host: 127.0.0.1
  3. port: 8182
  4. scriptEvaluationTimeout: 30000
  5. # If you want to start gremlin-server for gremlin-console(web-socket),
  6. # please change `HttpChannelizer` to `WebSocketChannelizer` or comment this line.
  7. channelizer: org.apache.tinkerpop.gremlin.server.channel.HttpChannelizer
  8. graphs: {
  9. hugegraph: conf/hugegraph.properties,
  10. hugegraph1: conf/hugegraph1.properties
  11. }
  12. plugins:
  13. - com.baidu.hugegraph
  14. scriptEngines: {
  15. gremlin-groovy: {
  16. imports: [java.lang.Math],
  17. staticImports: [java.lang.Math.PI],
  18. scripts: [scripts/empty-sample.groovy]
  19. }
  20. }
  21. serializers:
  22. - { className: org.apache.tinkerpop.gremlin.driver.ser.GryoLiteMessageSerializerV1d0,
  23. config: {
  24. serializeResultToString: false,
  25. ioRegistries: [com.baidu.hugegraph.io.HugeGraphIoRegistry]
  26. }
  27. }
  28. - { className: org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV1d0,
  29. config: {
  30. serializeResultToString: true,
  31. ioRegistries: [com.baidu.hugegraph.io.HugeGraphIoRegistry]
  32. }
  33. }
  34. - { className: org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerGremlinV1d0,
  35. config: {
  36. serializeResultToString: false,
  37. ioRegistries: [com.baidu.hugegraph.io.HugeGraphIoRegistry]
  38. }
  39. }
  40. - { className: org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerGremlinV2d0,
  41. config: {
  42. serializeResultToString: false,
  43. ioRegistries: [com.baidu.hugegraph.io.HugeGraphIoRegistry]
  44. }
  45. }
  46. - { className: org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV1d0,
  47. config: {
  48. serializeResultToString: false,
  49. ioRegistries: [com.baidu.hugegraph.io.HugeGraphIoRegistry]
  50. }
  51. }
  52. metrics: {
  53. consoleReporter: {enabled: false, interval: 180000},
  54. csvReporter: {enabled: true, interval: 180000, fileName: /tmp/gremlin-server-metrics.csv},
  55. jmxReporter: {enabled: false},
  56. slf4jReporter: {enabled: false, interval: 180000},
  57. gangliaReporter: {enabled: false, interval: 180000, addressingMode: MULTICAST},
  58. graphiteReporter: {enabled: false, interval: 180000}
  59. }
  60. maxInitialLineLength: 4096
  61. maxHeaderSize: 8192
  62. maxChunkSize: 8192
  63. maxContentLength: 65536
  64. maxAccumulationBufferComponents: 1024
  65. resultIterationBatchSize: 64
  66. writeBufferLowWaterMark: 32768
  67. writeBufferHighWaterMark: 65536
  68. ssl: {
  69. enabled: false
  70. }

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

然后进入gremlin-console

  1. bin/gremlin-console.sh
  2. objc[5761]: Class JavaLaunchHelper is implemented in both /Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/bin/java (0x10ec584c0) and /Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home/jre/lib/libinstrument.dylib (0x10ecdc4e0). One of the two will be used. Which one is undefined.
  3. \,,,/
  4. (o o)
  5. -----oOOo-(3)-oOOo-----
  6. plugin activated: com.baidu.hugegraph
  7. plugin activated: tinkerpop.server
  8. plugin activated: tinkerpop.utilities
  9. 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.GryoMessageSerializerV1d0,
  6. config: {
  7. serializeResultToString: true,
  8. ioRegistries: [com.baidu.hugegraph.io.HugeGraphIoRegistry]
  9. }
  10. }
  1. gremlin> :remote connect tinkerpop.server conf/remote.yaml
  2. 2018-01-15 15:30:31 11528 [main] [INFO ] org.apache.tinkerpop.gremlin.driver.Connection [] - Created new connection for ws://localhost:8182/gremlin
  3. 2018-01-15 15:30:31 11538 [main] [INFO ] org.apache.tinkerpop.gremlin.driver.Connection [] - Created new connection for ws://localhost:8182/gremlin
  4. 2018-01-15 15:30:31 11538 [main] [INFO ] org.apache.tinkerpop.gremlin.driver.ConnectionPool [] - Opening connection pool on Host{address=localhost/127.0.0.1:8182, hostUri=ws://localhost:8182/gremlin} with core size of 2
  5. ==>Configured localhost/127.0.0.1:8182

连接成功之后,在console的上下文中能使用的变量只有hugegraph和hugegraph1两个图对象(在gremlin-server.yaml中配置),如果想拥有更多的变量,可以在scripts/empty-sample.groovy中添加,如:

  1. import org.apache.tinkerpop.gremlin.server.util.LifeCycleHook
  2. // an init script that returns a Map allows explicit setting of global bindings.
  3. def globals = [:]
  4. // defines a sample LifeCycleHook that prints some output to the Gremlin Server console.
  5. // note that the name of the key in the "global" map is unimportant.
  6. globals << [hook: [
  7. onStartUp : { ctx ->
  8. ctx.logger.info("Executed once at startup of Gremlin Server.")
  9. },
  10. onShutDown: { ctx ->
  11. ctx.logger.info("Executed once at shutdown of Gremlin Server.")
  12. }
  13. ] as LifeCycleHook]
  14. // define schema manger for hugegraph
  15. schema = hugegraph.schema()
  16. // define the default TraversalSource to bind queries to - this one will be named "g".
  17. g = hugegraph.traversal()

这样在console中便可以直接使用schema和g这两个对象,做元数据的管理和图的查询了。

不定义了也没关系,因为所有的对象都可以通过graph获得,例如:

  1. gremlin> :> hugegraph.traversal().V()
  2. ==>v[2:ripple]
  3. ==>v[1:vadas]
  4. ==>v[1:peter]
  5. ==>v[1:josh]
  6. ==>v[1:marko]
  7. ==>v[2:lop]

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

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

  1. gremlin> script = """
  2. graph = hugegraph;
  3. marko = graph.addVertex(T.label, "person", "name", "marko", "age", 29, "city", "Beijing");
  4. vadas = graph.addVertex(T.label, "person", "name", "vadas", "age", 27, "city", "Hongkong");
  5. lop = graph.addVertex(T.label, "software", "name", "lop", "lang", "java", "price", 328);
  6. josh = graph.addVertex(T.label, "person", "name", "josh", "age", 32, "city", "Beijing");
  7. ripple = graph.addVertex(T.label, "software", "name", "ripple", "lang", "java", "price", 199);
  8. peter = graph.addVertex(T.label, "person", "name", "peter", "age", 35, "city", "Shanghai");
  9. marko.addEdge("knows", vadas, "date", "20160110", "weight", 0.5);
  10. marko.addEdge("knows", josh, "date", "20130220", "weight", 1.0);
  11. marko.addEdge("created", lop, "date", "20171210", "weight", 0.4);
  12. josh.addEdge("created", lop, "date", "20091111", "weight", 0.4);
  13. josh.addEdge("created", ripple, "date", "20171210", "weight", 1.0);
  14. peter.addEdge("created", lop, "date", "20170324", "weight", 0.2);
  15. graph.tx().commit();
  16. g = graph.traversal();
  17. g.V().toList().size();
  18. """
  19. gremlin> :> @script
  20. ==>6

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