Java
本文介紹如何基于Java編程環(huán)境連接和操作圖數(shù)據(jù)庫GDB。這是以常駐服務(wù)形式操作圖數(shù)據(jù)庫GDB的常用形式。
前提條件
圖數(shù)據(jù)庫GDB實例需要與ECS虛擬機處于同一個VPC中。
安裝Maven
添加具有Maven程序包的存儲庫。
wget http://repos.fedorapeople.org/repos/dchen/apache-maven/epel-apache-maven.repo\ -O /etc/yum.repos.d/epel-apache-maven.repo
設(shè)置該存儲庫的版本號。
sudo sed -i s/\$releasever/6/g /etc/yum.repos.d/epel-apache-maven.repo
下載并安裝Maven。
sudo yum install -y apache-maven
安裝Java
安裝JDK 8.0。
sudo yum install java-1.8.0-devel
如果您的ECS實例上有多個Java版本,請將Java8設(shè)置為默認運行。
sudo /usr/sbin/alternatives --config java 共有 4 個提供“java”的程序。 選項 命令 ----------------------------------------------- *+ 1 java-1.8.0-openjdk.x86_64 (/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.191.b12-1.el7_6.x86_64/jre/bin/java) 2 java-1.8.0-openjdk.x86_64 (/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.191.b12-0.el7_5.x86_64-debug/jre/bin/java) 3 java-1.7.0-openjdk.x86_64 (/usr/lib/jvm/java-1.7.0-openjdk-1.7.0.191-2.6.15.4.el7_5.x86_64/jre/bin/java) 4 /usr/lib/jvm/jre-1.6.0-openjdk.x86_64/bin/java
編寫Java客戶端代碼
創(chuàng)建gdb-gremlin-test的目錄。
mkdir gdb-gremlin-test; cd gdb-gremlin-test
創(chuàng)建pom.xml文件,并寫入如下內(nèi)容。
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.gdb.alibaba</groupId> <artifactId>GdbGremlinExample</artifactId> <packaging>jar</packaging> <version>1.0-SNAPSHOT</version> <name>GdbGremlinExample</name> <url>http://maven.apache.org</url> <dependencies> <dependency> <groupId>org.apache.tinkerpop</groupId> <artifactId>gremlin-driver</artifactId> <version>3.4.3</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>2.0.2</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>exec-maven-plugin</artifactId> <version>1.3</version> <configuration> <mainClass>com.gdb.alibaba.Test</mainClass> <complianceLevel>1.8</complianceLevel> </configuration> </plugin> </plugins> </build> </project>
創(chuàng)建目錄并新建文件。
mkdir -p src/main/java/com/gdb/alibaba/; touch src/main/java/com/gdb/alibaba/Test.java
編寫測試程序。
package com.gdb.alibaba; import org.apache.tinkerpop.gremlin.driver.Cluster; import org.apache.tinkerpop.gremlin.driver.Client; import org.apache.tinkerpop.gremlin.driver.Result; import org.apache.tinkerpop.gremlin.driver.ResultSet; import java.util.List; import java.util.Map; import java.util.HashMap; import java.io.File; public class Test { public static void main( String[] args ) { try { if(args.length != 1) { System.out.println("gdb-remote.yaml path needed"); return; } String yaml = args[0]; // 1. 初始化客戶端,客戶端包含連接池,線程安全,支持多線程并發(fā) Cluster cluster = Cluster.build(new File(yaml)).create(); Client client = cluster.connect().init(); // 2. 發(fā)送gremlin請求到GDB服務(wù)端,根據(jù)業(yè)務(wù)邏輯定制 String dsl = "g.addV(yourlabel).property(propertyKey, propertyValue)"; Map<String,Object> parameters = new HashMap<>(3); parameters.put("yourlabel","area"); parameters.put("propertyKey","wherence"); parameters.put("propertyValue","shenzheng"); ResultSet results = client.submit(dsl,parameters); List<Result> result = results.all().join(); result.forEach(p -> System.out.println(p.getObject())); // 3. 關(guān)閉客戶端,完成所有g(shù)remlin請求清理資源 client.close(); cluster.close(); } catch (Exception e) { System.out.println(e.getMessage()); } } }
說明SDK中client包含有連接池,支持多線程并發(fā)。業(yè)務(wù)上可以全局維護一個client,不需要每次請求都新建,等所有圖數(shù)據(jù)庫GDB請求處理完或者應(yīng)用退出時再關(guān)閉。
創(chuàng)建gdb-remote.yaml文件,該文件為Java客戶端與GDB圖數(shù)據(jù)庫建立連接的配置文件,其他詳細配置請參考SDK使用。
hosts: [ ${gdbHost} ] port: 8182 username: ${username} password: ${password} serializer: { className: org.apache.tinkerpop.gremlin.driver.ser.GraphBinaryMessageSerializerV1, config: { serializeResultToString: false } }
其中,示例參數(shù)說明如下:
參數(shù)
說明
${gdbHost}
GDB的連接地址,例如
gds-bp*******************.graphdb.rds.aliyuncs.com
。${username}
GDB的數(shù)據(jù)庫賬號。
${password}
GDB數(shù)據(jù)庫賬號對應(yīng)的密碼。
進入gdb-gremlin-test主目錄,編譯并執(zhí)行Java程序。
mvn compile exec:java -Dexec.args="/home/apache-tinkerpop-gmlin-console-3.4.0/conf/gdb-remote.yaml"
執(zhí)行結(jié)果如下:
v[ba8f60b7-0786-4014-a4e2-451f09b79878]
顯式配置客戶端
如果您需要集中管理配置,而不是使用單獨的GDB配置文件,可以通過Driver提供的API對客戶端進行顯式配置,示例代碼如下:
// 1. 初始化客戶端,客戶端包含連接池,線程安全,支持多線程并發(fā)
// Cluster cluster = Cluster.build(new File(yaml)).create();
// Client client = cluster.connect().init();
// 顯式配置客戶端
Cluster.build(${gdbHost}).port(${gdbPort}).
serializer(Serializers.GRAPHBINARY_V1D0).
maxConnectionPoolSize(8).
minConnectionPoolSize(8).
maxContentLength(65536).
credentials(${username}, ${password}).create();
client = cluster.connect().init();
其中,示例參數(shù)說明如下:
參數(shù) | 說明 |
| GDB的連接地址,例如 |
| GDB的端口號,例如 |
| GDB的數(shù)據(jù)庫賬號。 |
| GDB數(shù)據(jù)庫賬號對應(yīng)的密碼。 |
更多客戶端常用配置參數(shù)如下:
參數(shù) | 默認值 | 說明 |
connectionPool.maxContentLength | 65536 | 消息最大字節(jié)數(shù)。請求返回的數(shù)據(jù)量較大時需要增大該參數(shù)的值,否則可能出現(xiàn)返回結(jié)果無法處理的錯誤。 |
connectionPool.maxSize | 8 | 連接池最大連接數(shù)。并發(fā)較大的情況下建議增加最大連接數(shù)。 |
connectionPool.minSize | 2 | 連接池最小連接數(shù)。 |
更多dsl樣例
本文中以上示例內(nèi)容是適用參數(shù)化的方式,通過dsl g.addV(yourlabel).property(propertyKey, propertyValue)
和參數(shù)map
添加的點。以下內(nèi)容將結(jié)合具體的圖的點、邊結(jié)構(gòu)來進行更多的dsl示例。關(guān)于圖的點、邊結(jié)構(gòu)的介紹,請參見ThinkerPop文檔。
以下dsl示例需要改造成參數(shù)化的調(diào)用方式,您可以使用硬編碼方式來進行范例講解:
//DSL硬編碼:
dsl = "user_defined_dsl";
//比如:g.addV('sand131_id_5_99').property(id,'sand131_id_5_99').property('name','sand131_name_5_99')
ResultSet results = client.submit(dsl);
|
|
v
//參數(shù)化腳本:
String dsl ="g.addV(vertex).property(id,vertex).property('name',vertex)";
Map<String, Object> parameters = new HashMap<>();
parameters.put("vertex","sand131_id_5_99"); //填寫dsl語句中的vertex參數(shù)
ResultSet results = client.submit(dsl, parameters,timeoutInMillis);
示例步驟如下:
刪除指定label的點、邊。
g.E().hasLabel('gdb_sample_knows').drop() g.E().hasLabel('gdb_sample_created').drop() g.V().hasLabel('gdb_sample_person').drop() g.V().hasLabel('gdb_sample_software').drop()
添加頂點,為其設(shè)置id、property。
g.addV('gdb_sample_person').property(id, 'gdb_sample_marko').property('age', 28).property('name', 'marko') g.addV('gdb_sample_person').property(id, 'gdb_sample_vadas').property('age', 27).property('name', 'vadas') g.addV('gdb_sample_person').property(id, 'gdb_sample_josh').property('age', 32).property('name', 'josh') g.addV('gdb_sample_person').property(id, 'gdb_sample_peter').property('age', 35).property('name', 'peter') g.addV('gdb_sample_software').property(id, 'gdb_sample_lop').property('lang', 'java').property('name', 'lop') g.addV('gdb_sample_software').property(id, 'gdb_sample_ripple').property('lang', 'java').property('name', 'ripple')
修改或新增age屬性。
g.V('gdb_sample_marko').property('age', 29)
建立關(guān)系,設(shè)置屬性weight。
g.addE('gdb_sample_knows').from(V('gdb_sample_marko')).to(V('gdb_sample_vadas')).property('weight', 0.5f) g.addE('gdb_sample_knows').from(V('gdb_sample_marko')).to(V('gdb_sample_josh')).property('weight', 1.0f) g.addE('gdb_sample_created').from(V('gdb_sample_marko')).to(V('gdb_sample_lop')).property('weight', 0.4f) g.addE('gdb_sample_created').from(V('gdb_sample_josh')).to(V('gdb_sample_lop')).property('weight', 0.4f) g.addE('gdb_sample_created').from(V('gdb_sample_josh')).to(V('gdb_sample_ripple')).property('weight', 1.0f) g.addE('gdb_sample_created').from(V('gdb_sample_peter')).to(V('gdb_sample_lop')).property('weight', 0.2f)
查詢所有點或指定label的點數(shù)量。
g.V().count() g.V().hasLabel('gdb_sample_person').count()
查詢指定條件的頂點(>29歲的人,按name降序排列所有人)。
g.V().hasLabel('gdb_sample_person').has('age', gt(29)) g.V().hasLabel('gdb_sample_person').order().by('name', decr)
關(guān)聯(lián)查詢(獲取marko 認識的人, marko認識的人created的software)。
g.V('gdb_sample_marko').outE('gdb_sample_knows').inV().hasLabel('gdb_sample_person') g.V('gdb_sample_marko').outE('gdb_sample_knows').inV().hasLabel('gdb_sample_person').outE('gdb_sample_created').inV().hasLabel('gdb_sample_software')
刪除關(guān)系、頂點。
g.V('gdb_sample_marko').outE('gdb_sample_knows').where(inV().has(id, 'gdb_sample_josh')).drop() g.V('gdb_sample_marko').drop()
您也可以進行其他測試,詳細的Gremlin查詢語句,請參見TinkerPop的Gremlin文檔。