├── src ├── main │ ├── resources │ │ ├── application.properties │ │ └── conf │ │ │ ├── remote-graph.properties │ │ │ ├── remote-objects.yaml │ │ │ └── janusgraph-cql-es-server.properties │ └── java │ │ └── com │ │ └── example │ │ └── janusgraph │ │ ├── JanusgraphApplication.java │ │ ├── Example │ │ ├── SchemaVertex.java │ │ ├── SchemaProperties.java │ │ ├── CreateSchema.java │ │ └── GraphDataLand.java │ │ ├── config │ │ ├── JanusGraphConfig.java │ │ └── GraphSourceConfig.java │ │ ├── titExample │ │ ├── LandDataExample.java │ │ └── InitSchemaExample.java │ │ └── referenceExample │ │ ├── GraphOfTheGodsFactory.java │ │ └── RemoteGraphApp.java └── test │ └── java │ └── com │ └── example │ └── janusgraph │ ├── ExamplTest.java │ └── JanusgraphApplicationTests.java ├── .gitignore ├── 集群搭建.md ├── pom.xml ├── README.md └── LICENSE /src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/main/resources/conf/remote-graph.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bingbingll/janusgraph-example/HEAD/src/main/resources/conf/remote-graph.properties -------------------------------------------------------------------------------- /src/main/resources/conf/remote-objects.yaml: -------------------------------------------------------------------------------- 1 | hosts: [172.16.2.137] 2 | port: 8182 3 | serializer: { className: org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV1d0, 4 | config: { ioRegistries: [org.janusgraph.graphdb.tinkerpop.JanusGraphIoRegistry] }} -------------------------------------------------------------------------------- /src/main/java/com/example/janusgraph/JanusgraphApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.janusgraph; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class JanusgraphApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(JanusgraphApplication.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/** 5 | !**/src/test/** 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | 30 | ### VS Code ### 31 | .vscode/ 32 | -------------------------------------------------------------------------------- /src/main/java/com/example/janusgraph/Example/SchemaVertex.java: -------------------------------------------------------------------------------- 1 | package com.example.janusgraph.Example; 2 | 3 | import org.springframework.stereotype.Component; 4 | 5 | /** 6 | * @author 李兵 7 | * @version V1.0 8 | * @description TODO: 9 | * @date 2019/9/5 20:58 10 | */ 11 | @Component 12 | public class SchemaVertex { 13 | public static final String PERSON = "person"; 14 | public static final String LOCALHOST = "localhost"; 15 | public static final String COMPANY = "company"; 16 | } 17 | -------------------------------------------------------------------------------- /集群搭建.md: -------------------------------------------------------------------------------- 1 | 这里介绍Cassandra和es的集群搭建 2 | # 官网搭建介绍 3 | * 高级JanusGraph架构和上下文: [架构图](https://docs.janusgraph.org/latest/images/architecture-layer-diagram.svg) 4 | 5 | ## 搭建方式 6 | 7 | >### 单机搭建 8 | 1客户端 、2 janusGrph(配置)、3单机集群(后端) 9 | 10 | >### 分布式搭建 11 | 1客户端 、2 janusGraph集群、3存储集群(后端) 12 | 13 | >### 分布式 服务器形式搭建(+gremlinServer ) 14 | 1客户端 、2 janusGraph集群+gremlinServer(janusGraph server)、3存储集群(后端) 15 | 16 | >### 参考连接 ### 17 | [参考连接](https://www.jianshu.com/p/2f4ef7c33125),[官网介绍](https://docs.janusgraph.org/latest/cassandra.html) 18 | 19 | 20 | ### 版本兼容 ### 21 | JanusGraph项目与图表和大数据生态系统的其余部分一起发展,并利用存储和索引后端。以下是各种组件版本之间的版本兼容性。对于从属后端系统,通常也支持不同的次要版本。强烈建议在部署JanusGraph之前验证版本兼容性。 22 | 23 | 尽管JanusGraph可能与较旧且不再受支持的依赖版本兼容,但会警告用户,不再支持或更新运行的软件可能存在风险和安全风险。请与软件提供商联系以了解其支持的版本。强烈建议用户使用最新版本的软件。 24 | 25 | [版本支持](https://docs.janusgraph.org/latest/version-compat.html) -------------------------------------------------------------------------------- /src/main/java/com/example/janusgraph/Example/SchemaProperties.java: -------------------------------------------------------------------------------- 1 | package com.example.janusgraph.Example; 2 | 3 | 4 | /** 5 | * @author 李兵 6 | * @version V1.0 7 | * @description TODO: 属性实体类 8 | * @date 2019/9/5 21:01 9 | */ 10 | public class SchemaProperties { 11 | /**名称*/ 12 | public static final String NAME="name"; 13 | /**年龄*/ 14 | public static final String AGE="age"; 15 | /**性别*/ 16 | public static final String GENDER="gender"; 17 | /**身份证号*/ 18 | public static final String NO="no"; 19 | /**时间,可以为公司成立时间,人员的入职时间的这是一个笼统的定义*/ 20 | public static final String TIME="time"; 21 | /**手机/电话*/ 22 | public static final String PHONE="phone"; 23 | /**关系型数据库的主键*/ 24 | public static final String ID="id"; 25 | 26 | /**地方*/ 27 | public static final String ADDRESS="address"; 28 | /**坐标*/ 29 | public static final String PLACE="place"; 30 | } 31 | -------------------------------------------------------------------------------- /src/test/java/com/example/janusgraph/ExamplTest.java: -------------------------------------------------------------------------------- 1 | package com.example.janusgraph; 2 | 3 | import com.example.janusgraph.Example.CreateSchema; 4 | import com.example.janusgraph.Example.GraphDataLand; 5 | import com.example.janusgraph.config.GraphSourceConfig; 6 | import com.example.janusgraph.config.JanusGraphConfig; 7 | import org.apache.tinkerpop.gremlin.driver.Client; 8 | import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; 9 | import org.junit.Test; 10 | import org.junit.runner.RunWith; 11 | import org.springframework.beans.factory.annotation.Autowired; 12 | import org.springframework.boot.test.context.SpringBootTest; 13 | import org.springframework.test.context.junit4.SpringRunner; 14 | 15 | /** 16 | * @author 李兵 17 | * @version V1.0 18 | * @description TODO: 19 | * @date 2019/9/6 16:15 20 | */ 21 | @RunWith(SpringRunner.class) 22 | @SpringBootTest 23 | public class ExamplTest { 24 | @Autowired 25 | CreateSchema schema; 26 | @Autowired 27 | GraphDataLand land; 28 | @Autowired 29 | GraphSourceConfig graphSourceConfig; 30 | @Autowired 31 | JanusGraphConfig janusGraphConfig; 32 | 33 | 34 | /** 35 | * 使用Graph Structure(结构)进行创建和定义数据模型 36 | */ 37 | @Test 38 | public void testSchema() { 39 | 40 | try { 41 | schema.createProperties(janusGraphConfig.mgt); 42 | schema.createVertexLabels(janusGraphConfig.mgt); 43 | schema.createEdgeLabels(janusGraphConfig.mgt); 44 | schema.createCompositeIndexes(janusGraphConfig.mgt); 45 | schema.createMixedIndexes(janusGraphConfig.mgt); 46 | } catch (Exception e) { 47 | e.printStackTrace(); 48 | janusGraphConfig.rollback(); 49 | } finally { 50 | janusGraphConfig.close(); 51 | } 52 | } 53 | 54 | /** 55 | * 使用Graph Process(处理)创建数据并插入到schema数据模型中 56 | */ 57 | @Test 58 | public void testLand() { 59 | Client client = graphSourceConfig.getClient(); 60 | GraphTraversalSource g = graphSourceConfig.getGts4(client); 61 | land.createElements2(g); 62 | graphSourceConfig.close(g, client); 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /src/test/java/com/example/janusgraph/JanusgraphApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.example.janusgraph; 2 | 3 | import com.example.janusgraph.config.GraphSourceConfig; 4 | import org.apache.tinkerpop.gremlin.driver.Client; 5 | import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal; 6 | import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; 7 | import org.apache.tinkerpop.gremlin.structure.Vertex; 8 | import org.junit.Test; 9 | import org.junit.runner.RunWith; 10 | import org.springframework.boot.test.context.SpringBootTest; 11 | import org.springframework.test.context.junit4.SpringRunner; 12 | 13 | import java.util.Map; 14 | 15 | @RunWith(SpringRunner.class) 16 | @SpringBootTest 17 | 18 | public class JanusgraphApplicationTests { 19 | GraphSourceConfig config = new GraphSourceConfig(); 20 | 21 | @Test 22 | public void testAdd() throws Exception { 23 | GraphTraversalSource g = config.getGts1(); 24 | Vertex next = g.addV("测试1") 25 | .property("name", "测试1") 26 | .property("age", "25") 27 | .property("no", "11111111") 28 | .next(); 29 | } 30 | 31 | @Test 32 | public void testAdd2() throws Exception { 33 | GraphTraversalSource g = config.getGts2(); 34 | try { 35 | g.addV("测试2") 36 | .property("name", "测试2", "no", "2222222", "addr", "北京市海淀区") 37 | .next(); 38 | } catch (Exception e) { 39 | e.printStackTrace(); 40 | } finally { 41 | g.close(); 42 | } 43 | } 44 | 45 | @Test 46 | public void testAdd31() { 47 | GraphTraversalSource g = null; 48 | Client client = config.getClient(); 49 | try { 50 | client.submit("g.addV('测试3').property('name','测试3','no','3333333','addr','北京市海淀区')"); 51 | } catch (Exception e) { 52 | e.printStackTrace(); 53 | } finally { 54 | config.close(g, client); 55 | } 56 | } 57 | 58 | @Test 59 | public void testAdd4() throws Exception { 60 | Client client = config.getClient(); 61 | GraphTraversalSource g = config.getGts4(client); 62 | try { 63 | g.addV("测试444").property("name", "测试444", "no", "44444444").next(); 64 | } catch (Exception e) { 65 | e.printStackTrace(); 66 | } finally { 67 | config.close(g, client); 68 | 69 | } 70 | } 71 | 72 | 73 | @Test 74 | public void testGetVal() throws Exception { 75 | GraphTraversalSource g = config.getGts1(); 76 | GraphTraversal> vmgt = g.V().valueMap(true); 77 | System.out.println(vmgt.hasNext()); 78 | while (vmgt.hasNext()) { 79 | System.out.println(vmgt.next().toString()); 80 | } 81 | } 82 | 83 | } -------------------------------------------------------------------------------- /src/main/java/com/example/janusgraph/config/JanusGraphConfig.java: -------------------------------------------------------------------------------- 1 | package com.example.janusgraph.config; 2 | 3 | import lombok.extern.log4j.Log4j2; 4 | import org.apache.tinkerpop.gremlin.structure.Transaction; 5 | import org.janusgraph.core.JanusGraph; 6 | import org.janusgraph.core.JanusGraphFactory; 7 | import org.janusgraph.core.schema.JanusGraphManagement; 8 | import org.springframework.context.annotation.Configuration; 9 | 10 | import java.net.URLDecoder; 11 | 12 | /** 13 | * @author 李兵 14 | * @version V1.0 15 | * @description TODO: 16 | * @date 2019/9/3 17:09 17 | */ 18 | @Configuration 19 | @Log4j2 20 | public class JanusGraphConfig { 21 | private static final String CONFIG_FILE = "conf/janusgraph-cql-es-server.properties"; 22 | public final JanusGraph graph; 23 | public final JanusGraphManagement mgt; 24 | 25 | /** 26 | * Initialize the graph and the graph management interface. 27 | * 使用无参构造 28 | */ 29 | public JanusGraphConfig() { 30 | try { 31 | // this.dropOldKeyspace(); 32 | } catch (Exception ex) { 33 | log.info("Cannot drop keyspace janusgraph"); 34 | } 35 | 36 | 37 | String path = Thread.currentThread() 38 | .getContextClassLoader() 39 | .getResource(CONFIG_FILE).getPath().substring(1); 40 | 41 | String decode = ""; 42 | try { 43 | decode = URLDecoder.decode(path); 44 | } catch (Exception e) { 45 | e.printStackTrace(); 46 | log.error("获取配置文件路径错误原因:" + e.getLocalizedMessage()); 47 | } 48 | log.info("Connecting graph"); 49 | graph = JanusGraphFactory.open(decode); 50 | log.info("Getting management"); 51 | mgt = graph.openManagement(); 52 | } 53 | 54 | // private void dropOldKeyspace() { 55 | // TTransport tr = new TFramedTransport(new TSocket("localhost", 9160)); 56 | // TProtocol proto = new TBinaryProtocol(tr); 57 | // Cassandra.Client client = new Cassandra.Client(proto); 58 | // tr.open(); 59 | // 60 | // client.system_drop_keyspace(JANUSGRAPH); 61 | // LOGGER.info("DROPPED keyspace janusgraph"); 62 | // tr.close(); 63 | // } 64 | 65 | 66 | public void close() { 67 | mgt.commit(); 68 | graph.close(); 69 | } 70 | 71 | public void rollback() { 72 | Transaction tx = graph.tx(); 73 | tx.rollback(); 74 | } 75 | 76 | /**此方法也可以获取**/ 77 | // public JanusGraph getJanusGraph1() { 78 | // JanusGraphFactory.Builder build = JanusGraphFactory.build() 79 | // .set("storage.backend", "cql") 80 | // .set("storage.cassandra.keyspace", "test") 81 | // .set("storage.hostname", "172.16.2.138") 82 | // .set("storage.port", "9042") 83 | // .set("index.search.backend", "elasticsearch") 84 | // .set("index.search.hostname", "172.16.2.137") 85 | // .set("cache.db-cache", "true") 86 | // .set("cache.db-cache-time", "3000000") 87 | // .set("cache.db-cache-size", "0.25"); 88 | // JanusGraph janusGraph = build.open(); 89 | // boolean open = janusGraph.isOpen(); 90 | // if (open) { 91 | // System.out.println("janusgraph open"); 92 | // return janusGraph; 93 | // } 94 | // return null; 95 | // } 96 | } 97 | -------------------------------------------------------------------------------- /src/main/java/com/example/janusgraph/titExample/LandDataExample.java: -------------------------------------------------------------------------------- 1 | package com.example.janusgraph.titExample; 2 | 3 | import com.github.javafaker.Faker; 4 | import org.apache.tinkerpop.gremlin.structure.Edge; 5 | import org.apache.tinkerpop.gremlin.structure.Vertex; 6 | import org.janusgraph.core.JanusGraph; 7 | import org.springframework.stereotype.Component; 8 | 9 | import java.util.Calendar; 10 | import java.util.Date; 11 | 12 | /** 13 | * 14 | */ 15 | @Component 16 | @Deprecated 17 | public class LandDataExample { 18 | 19 | private final Faker faker; 20 | private final Date oneMonthAgo; 21 | 22 | /** 23 | * 初始化 24 | */ 25 | public LandDataExample() { 26 | this.faker=new Faker(); 27 | Calendar cal = Calendar.getInstance(); 28 | cal.add(Calendar.MONTH, -1); 29 | this.oneMonthAgo = cal.getTime(); 30 | } 31 | 32 | 33 | /** 34 | * 循环添加 35 | * @param count 36 | * @return 37 | */ 38 | public Vertex[] generateUsers(int count,JanusGraph janusGraph){ 39 | Vertex[] users = new Vertex[count]; 40 | 41 | for(int i=0; i < count; i++){ 42 | users[i] = addUser("testUser" + i,janusGraph); 43 | } 44 | 45 | return users; 46 | } 47 | 48 | /** 49 | * 循环添加 50 | * @param user 51 | * @param count 52 | * @return 53 | */ 54 | public Vertex[] generateStatusUpdates(Vertex user, int count,JanusGraph janusGraph){ 55 | Vertex[] updates = new Vertex[count]; 56 | for(int i=0; i < count; i++) { 57 | updates[i] = addStatusUpdatew(user, getContent(),janusGraph); 58 | } 59 | return updates; 60 | } 61 | 62 | public void commit(JanusGraph janusGraph){ 63 | janusGraph.tx().commit(); 64 | } 65 | 66 | /** 67 | * Commit the current transaction and close the graph. 68 | */ 69 | private void close(JanusGraph janusGraph){ 70 | commit(janusGraph); 71 | janusGraph.close(); 72 | } 73 | 74 | /** 75 | * 添加1个顶点 76 | * @param userName 77 | * @return 78 | */ 79 | private Vertex addUser(String userName,JanusGraph janusGraph){ 80 | Vertex user = janusGraph.addVertex(InitSchemaExample.USER); 81 | user.property(InitSchemaExample.USER_NAME, userName); 82 | return user; 83 | } 84 | 85 | /** 86 | * 添加1个点 87 | * @param user 88 | * @param statusUpdateContent 89 | * @return 90 | */ 91 | private Vertex addStatusUpdatew(Vertex user, String statusUpdateContent,JanusGraph janusGraph) { 92 | Vertex statusUpdate = janusGraph.addVertex(InitSchemaExample.STATUS_UPDATE); 93 | statusUpdate.property(InitSchemaExample.CONTENT, statusUpdateContent); 94 | user.addEdge(InitSchemaExample.POSTS, statusUpdate, InitSchemaExample.CREATED_AT, getTimestamp()); 95 | return statusUpdate; 96 | } 97 | 98 | /** 99 | * 添加边 100 | * @param forUser 101 | * @param users 102 | * @param count 103 | * @return 104 | */ 105 | public Vertex[] generateFollows(Vertex forUser, Vertex[] users, int count){ 106 | Vertex[] followedUsers = new Vertex[count]; 107 | 108 | for(int i = 0; i < count; i++) { 109 | followedUsers[i] = users[faker.number().numberBetween(0, users.length - 1)]; 110 | Edge follows = forUser.addEdge(InitSchemaExample.FOLLOWS, followedUsers[i], InitSchemaExample.CREATED_AT, getTimestamp()); 111 | } 112 | return followedUsers; 113 | } 114 | 115 | 116 | 117 | 118 | /** 119 | * Return a timestamp between 1 month ago and now. 120 | * @return 121 | */ 122 | private Long getTimestamp(){ 123 | return faker.date().between(oneMonthAgo, new Date()).getTime(); 124 | } 125 | 126 | private String getContent(){ 127 | return faker.chuckNorris().fact(); 128 | } 129 | 130 | 131 | } 132 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | org.springframework.boot 7 | spring-boot-starter-parent 8 | 2.1.7.RELEASE 9 | 10 | 11 | com.example 12 | janusgraph 13 | 0.0.1-SNAPSHOT 14 | janusgraph 15 | Demo janusgraph for Spring Boot 16 | 17 | 18 | 1.8 19 | 20 | 21 | 22 | 23 | org.springframework.boot 24 | spring-boot-starter-web-services 25 | 26 | 27 | 28 | org.springframework.boot 29 | spring-boot-devtools 30 | runtime 31 | true 32 | 33 | 34 | org.projectlombok 35 | lombok 36 | true 37 | 38 | 39 | org.springframework.boot 40 | spring-boot-starter-test 41 | test 42 | 43 | 44 | 45 | 46 | org.apache.tinkerpop 47 | gremlin-driver 48 | 3.4.1 49 | 50 | 51 | org.janusgraph 52 | janusgraph-core 53 | 0.4.0 54 | 55 | 56 | 57 | org.janusgraph 58 | example-common 59 | 0.4.0 60 | 61 | 62 | org.janusgraph 63 | janusgraph-core 64 | 65 | 66 | 67 | 68 | 69 | 70 | org.janusgraph 71 | janusgraph-cql 72 | 0.4.0 73 | 74 | 75 | com.codahale.metrics 76 | metrics-core 77 | 3.0.2 78 | 79 | 80 | org.janusgraph 81 | janusgraph-cassandra 82 | 0.4.0 83 | 84 | 85 | org.janusgraph 86 | janusgraph-es 87 | 0.4.0 88 | 89 | 90 | 91 | 92 | com.github.javafaker 93 | javafaker 94 | 1.0.1 95 | 96 | 97 | 98 | 99 | 100 | 101 | org.springframework.boot 102 | spring-boot-maven-plugin 103 | 104 | 105 | 106 | 107 | 108 | -------------------------------------------------------------------------------- /src/main/java/com/example/janusgraph/config/GraphSourceConfig.java: -------------------------------------------------------------------------------- 1 | package com.example.janusgraph.config; 2 | 3 | import lombok.extern.log4j.Log4j2; 4 | import org.apache.tinkerpop.gremlin.driver.Client; 5 | import org.apache.tinkerpop.gremlin.driver.Cluster; 6 | import org.apache.tinkerpop.gremlin.driver.remote.DriverRemoteConnection; 7 | import org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV3d0; 8 | import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; 9 | import org.apache.tinkerpop.gremlin.structure.Graph; 10 | import org.apache.tinkerpop.gremlin.structure.io.gryo.GryoMapper; 11 | import org.apache.tinkerpop.gremlin.structure.util.empty.EmptyGraph; 12 | import org.janusgraph.graphdb.tinkerpop.JanusGraphIoRegistry; 13 | import org.springframework.context.annotation.Configuration; 14 | 15 | import java.net.URLDecoder; 16 | 17 | import static org.apache.tinkerpop.gremlin.process.traversal.AnonymousTraversalSource.traversal; 18 | 19 | /** 20 | * @author 李兵 21 | * @version V1.0 22 | * @description TODO: 获取图对象配置 23 | * @date 2019/8/30 20:05 24 | */ 25 | @Configuration 26 | @Log4j2 27 | public class GraphSourceConfig { 28 | 29 | /** 30 | * 基于官网介绍编写1 31 | * TODO:需要修改 remote-graph.properties 配置文件的gremlin.remote.driver.clusterFile=值为绝对路径 32 | * 33 | * @return 34 | * @throws Exception 35 | */ 36 | public GraphTraversalSource getGts1() throws Exception { 37 | Graph graph = EmptyGraph.instance(); 38 | //不这样写获取读不到文件路径 39 | String path = getClass().getClassLoader().getResource("conf/remote-graph.properties").getPath(); 40 | String decode = URLDecoder.decode(path.substring(1), "utf-8"); 41 | GraphTraversalSource g = graph.traversal().withRemote(decode); 42 | return g; 43 | } 44 | 45 | /** 46 | * 基于官网介绍编写2 47 | * TODO:需要修改 remote-graph.properties 配置文件的gremlin.remote.driver.clusterFile=值为绝对路径 48 | * 49 | * @return 50 | * @throws Exception 51 | */ 52 | public GraphTraversalSource getGts2() throws Exception { 53 | String path1 = Thread.currentThread() 54 | .getContextClassLoader() 55 | .getResource("conf/remote-graph.properties").getPath(); 56 | GraphTraversalSource g = traversal().withRemote(java.net.URLDecoder.decode(path1.substring(1), "utf-8")); 57 | return g; 58 | } 59 | 60 | 61 | /** 62 | * 基于官网介绍编写3 63 | */ 64 | public GraphTraversalSource getGts3() { 65 | GraphTraversalSource g = traversal() 66 | .withRemote( 67 | DriverRemoteConnection.using("172.16.2.137", 8182, "g") 68 | ); 69 | return g; 70 | } 71 | 72 | 73 | /** 74 | * 池的写法 75 | * 76 | * @return 77 | */ 78 | public Cluster getCluster() { 79 | GryoMapper.Builder builder = GryoMapper.build(). 80 | addRegistry(JanusGraphIoRegistry.getInstance()); 81 | GryoMessageSerializerV3d0 serializer = new GryoMessageSerializerV3d0(builder); 82 | //Caused by: io.netty.handler.codec.DecoderException: org.apache.tinkerpop.gremlin.driver.ser.SerializationException: org.apache.tinkerpop.shaded.kryo.KryoException: Encountered unregistered class ID: 65536 83 | //https://github.com/orientechnologies/orientdb-gremlin/issues/161 84 | 85 | //TODO:配置地址-> http://tinkerpop.apache.org/javadocs/3.4.1/core/org/apache/tinkerpop/gremlin/driver/Cluster.Builder.html 86 | return Cluster.build() 87 | .serializer(serializer) 88 | .maxConnectionPoolSize(20) 89 | .maxInProcessPerConnection(15) 90 | .maxWaitForConnection(3000) 91 | .reconnectInterval(10) 92 | //可配置多个,是你的janusgraph 的地址 93 | .addContactPoint("172.16.2.137") 94 | .port(8182) 95 | .create(); 96 | } 97 | 98 | public Client getClient() { 99 | Cluster cluster = getCluster(); 100 | return cluster.connect(); 101 | } 102 | 103 | /** 104 | * 基于官网介绍编写4 105 | * 106 | * @return 107 | */ 108 | public GraphTraversalSource getGts4(Client client) { 109 | GraphTraversalSource g = traversal(). 110 | withRemote(DriverRemoteConnection. 111 | using(client, "g") 112 | ); 113 | return g; 114 | } 115 | 116 | 117 | public void close(GraphTraversalSource g, Client client) { 118 | try { 119 | g.close(); 120 | client.close(); 121 | } catch (Exception e) { 122 | e.printStackTrace(); 123 | } 124 | } 125 | 126 | } 127 | -------------------------------------------------------------------------------- /src/main/java/com/example/janusgraph/titExample/InitSchemaExample.java: -------------------------------------------------------------------------------- 1 | package com.example.janusgraph.titExample; 2 | 3 | import com.example.janusgraph.config.JanusGraphConfig; 4 | import com.example.janusgraph.config.GraphSourceConfig; 5 | import lombok.extern.log4j.Log4j2; 6 | import org.apache.tinkerpop.gremlin.structure.Edge; 7 | import org.apache.tinkerpop.gremlin.structure.Vertex; 8 | import org.janusgraph.core.EdgeLabel; 9 | import org.janusgraph.core.JanusGraph; 10 | import org.janusgraph.core.PropertyKey; 11 | import org.janusgraph.core.VertexLabel; 12 | import org.janusgraph.core.schema.JanusGraphManagement; 13 | import org.janusgraph.core.schema.Mapping; 14 | import org.springframework.beans.factory.annotation.Autowired; 15 | 16 | /** 17 | * 初始化一个schema,并设定顶点,边,属性 18 | */ 19 | @Log4j2 20 | @Deprecated 21 | public class InitSchemaExample { 22 | @Autowired 23 | GraphSourceConfig graphSource; 24 | /** 25 | * The index backend is identified by a key in the configuration; in our example we called it 26 | *
search
. 27 | *
28 | * Saving it in a static variable so we can reuse. 29 | */ 30 | public static final String BACKING_INDEX = "search"; 31 | 32 | public static final String USER = "user"; 33 | public static final String USER_NAME = "marcelocf.janusgraph.userName"; 34 | 35 | public static final String STATUS_UPDATE = "statusUpdate"; 36 | public static final String CONTENT = "marcelocf.janusgraph.content"; 37 | 38 | public static final String CREATED_AT = "marcelocf.janusgraph.createdAt"; 39 | 40 | public static final String POSTS = "posts"; 41 | public static final String FOLLOWS = "follows"; 42 | 43 | 44 | /** 45 | * Create the user schema - vertex label, property and index. 46 | */ 47 | private void createSchema(JanusGraphManagement mgt) { 48 | 49 | VertexLabel user = mgt.makeVertexLabel(USER).make(); 50 | PropertyKey userName = mgt.makePropertyKey(USER_NAME).dataType(String.class).make(); 51 | 52 | mgt.buildIndex(indexName(USER, USER_NAME), Vertex.class). 53 | addKey(userName, Mapping.STRING.asParameter()). 54 | indexOnly(user). 55 | buildMixedIndex(BACKING_INDEX); 56 | } 57 | 58 | /** 59 | * Create the statusUpdate schema - vertex label, property and full-text index. 60 | */ 61 | private void createStatusUpdateSchema(JanusGraphManagement mgt) { 62 | log.info("Create {} schema", STATUS_UPDATE); 63 | VertexLabel statusUpdate = mgt.makeVertexLabel(STATUS_UPDATE).make(); 64 | PropertyKey content = mgt.makePropertyKey(CONTENT).dataType(String.class).make(); 65 | 66 | mgt.buildIndex(indexName(STATUS_UPDATE, CONTENT), Vertex.class). 67 | addKey(content, Mapping.TEXTSTRING.asParameter()). 68 | indexOnly(statusUpdate). 69 | buildMixedIndex(BACKING_INDEX); 70 | } 71 | 72 | /** 73 | * Create both posts and follows edges and related index. 74 | *
75 | *

76 | * Because the property and index for both follows and posts is the same we create them at the same point here. 77 | */ 78 | private void createEdgeSchema(JanusGraphManagement mgt) { 79 | log.info("create edges schema"); 80 | EdgeLabel posts = mgt.makeEdgeLabel(POSTS).make(); 81 | EdgeLabel follows = mgt.makeEdgeLabel(FOLLOWS).make(); 82 | PropertyKey createdAt = mgt.makePropertyKey(CREATED_AT).dataType(Long.class).make(); 83 | 84 | mgt.buildIndex(indexName(POSTS, CREATED_AT), Edge.class). 85 | addKey(createdAt). 86 | indexOnly(posts). 87 | buildMixedIndex(BACKING_INDEX); 88 | 89 | mgt.buildIndex(indexName(FOLLOWS, CREATED_AT), Edge.class). 90 | addKey(createdAt). 91 | indexOnly(follows). 92 | buildMixedIndex(BACKING_INDEX); 93 | } 94 | 95 | /** 96 | * We are using this to create predictable names for our indexes. You could name it however you want, but doing 97 | * like this will make it possible to reindex stuff in the future... if we want (we do want, btw) 98 | * 99 | * @param label edge or vertex label 100 | * @param propertyKey property key 101 | * @return 102 | */ 103 | public static String indexName(String label, String propertyKey) { 104 | return label + ":by:" + propertyKey; 105 | } 106 | 107 | 108 | /** 109 | * Commit the current transaction and close the graph. 110 | */ 111 | private void close(JanusGraphManagement mgt, JanusGraph graph) { 112 | mgt.commit(); 113 | graph.tx().commit(); 114 | graph.close(); 115 | } 116 | 117 | 118 | public static void main(String[] args) { 119 | JanusGraphConfig getGraphAndMgt = new JanusGraphConfig(); 120 | JanusGraphManagement mgt = getGraphAndMgt.mgt; 121 | JanusGraph graph = getGraphAndMgt.graph; 122 | InitSchemaExample jgExample = new InitSchemaExample(); 123 | jgExample.createSchema(mgt); 124 | jgExample.createStatusUpdateSchema(mgt); 125 | jgExample.createEdgeSchema(mgt); 126 | jgExample.close(mgt, graph); 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /src/main/java/com/example/janusgraph/Example/CreateSchema.java: -------------------------------------------------------------------------------- 1 | package com.example.janusgraph.Example; 2 | 3 | import lombok.extern.log4j.Log4j2; 4 | import org.apache.tinkerpop.gremlin.structure.Edge; 5 | import org.apache.tinkerpop.gremlin.structure.Vertex; 6 | import org.janusgraph.core.Cardinality; 7 | import org.janusgraph.core.attribute.Geoshape; 8 | import org.janusgraph.core.schema.JanusGraphManagement; 9 | import org.springframework.stereotype.Service; 10 | 11 | import static org.janusgraph.core.Multiplicity.MANY2ONE; 12 | 13 | /** 14 | * @author 李兵 15 | * @version V1.0 16 | * @description TODO: 定义schema,这里的业务模型为,一个人,一个公司, 17 | * @date 2019/9/5 19:21 18 | */ 19 | @Service 20 | @Log4j2 21 | public class CreateSchema { 22 | 23 | 24 | protected boolean useMixedIndex = true; 25 | protected String mixedIndexConfigName = "search"; 26 | 27 | /** 28 | * 定义schema图的顶点(我喜欢叫这个为所属类型); 人:person,公司:company,地点:localhost 三个顶点 29 | * 30 | * @param management 31 | */ 32 | public void createVertexLabels(JanusGraphManagement management) { 33 | management.makeVertexLabel(SchemaVertex.PERSON).make(); 34 | management.makeVertexLabel(SchemaVertex.LOCALHOST).make(); 35 | management.makeVertexLabel(SchemaVertex.COMPANY).make(); 36 | } 37 | 38 | /** 39 | * 定义属性,及图中的属性属性,可以为边,点,进行引用。 40 | * 使用基数(基数)来定义与任何给定顶点上的键相关联的值的允许基数。 41 | * SINGLE:对于此类密钥,每个元素最多允许一个值。换句话说,键→值映射对于图中的所有元素都是唯一的。 42 | * 属性键birthDate是具有SINGLE基数的示例,因为每个人只有一个出生日期。 43 | * LIST:允许每个元素的任意数量的值用于此类键。换句话说,密钥与允许重复值的值列表相关联。 44 | * 假设我们将传感器建模为图形中的顶点,则属性键sensorReading是LIST基数的示例,允许记录大量(可能重复的)传感器读数。 45 | * SET:允许多个值,但每个元素没有重复值用于此类键。换句话说,密钥与一组值相关联。 46 | * 如果我们想要捕获个人的所有姓名(包括昵称,婚前姓名等),则属性键名称具有SET基数。 47 | *

48 | * 默认基数设置为SINGLE。请注意,边和属性上使用的属性键具有基数SINGLE。不支持为边或属性上的单个键附加多个值。 49 | * 50 | * @param management 51 | */ 52 | public void createProperties(JanusGraphManagement management) { 53 | //名称,可以由多个名称 54 | management.makePropertyKey(SchemaProperties.NAME).dataType(String.class).cardinality(Cardinality.SET).make(); 55 | //年龄, 56 | management.makePropertyKey(SchemaProperties.AGE).dataType(Integer.class).make(); 57 | //身份证号 58 | management.makePropertyKey(SchemaProperties.NO).dataType(String.class).make(); 59 | //时间,可以为公司成立时间,人员的入职时间的这是一个笼统的定义 60 | management.makePropertyKey(SchemaProperties.TIME).dataType(String.class).make(); 61 | //手机/电话 62 | management.makePropertyKey(SchemaProperties.PHONE).dataType(String.class).make(); 63 | //关系型数据库的主键 64 | management.makePropertyKey(SchemaProperties.ID).dataType(String.class).make(); 65 | //地方 66 | management.makePropertyKey(SchemaProperties.ADDRESS).dataType(String.class).make(); 67 | //公司坐标 68 | management.makePropertyKey(SchemaProperties.PLACE).dataType(Geoshape.class).make(); 69 | } 70 | 71 | /** 72 | * 定义schema图的边; 73 | *

74 | * MULTI: 允许任何顶点对之间的同一标签的多个边。换句话说,该图是关于这种边缘标签的多图。边缘多重性没有约束。 75 | * SIMPLE:在任何一对顶点之间最多允许此类标签的一个边缘。换句话说,该图是关于标签的简单图。确保边缘对于给定标签和顶点对是唯一的 76 | * MANY2ONE:在图形中的任何顶点上最多允许此标签的一个输出,但不对入射边缘施加约束。 77 | * 边缘标签母亲是MANY2ONE多样性的一个例子,因为每个人最多只有一个母亲,但母亲可以有多个孩子。 78 | * ONE2MANY:在图形中的任何顶点上最多允许此类标签的一个输入边缘,但不对输出边缘施加约束。 79 | * 边缘标签winnerOf是具有ONE2MANY多样性的示例,因为每个比赛最多只能赢得一个人,但是一个人可以赢得多个比赛. 80 | * ONE2ONE:在图中的任何顶点上最多允许此标签的一个输入边和一个输出边。边缘标签结婚是一个具有ONE2ONE多样性的例子,因为一个人与另一个人结婚。 81 | * todo:默认设置为 MULTI。 82 | * todo:具体参考这位同学写的链接:https://www.cnblogs.com/jiyuqi/p/7127178.html?utm_source=itdadao&utm_medium=referral 83 | * 84 | * @param management 85 | */ 86 | public void createEdgeLabels(JanusGraphManagement management) { 87 | //父亲,注意这里的 Multiplicity常量, 88 | management.makeEdgeLabel("father").multiplicity(MANY2ONE).make(); 89 | //母亲 90 | management.makeEdgeLabel("mother").multiplicity(MANY2ONE).make(); 91 | //兄弟或平辈 92 | management.makeEdgeLabel("brother").make(); 93 | //归属,人属于哪个公司,公司中都有谁 公司地点在哪里 94 | management.makeEdgeLabel("belong").make(); 95 | } 96 | 97 | /** 98 | * 复合索引 99 | * 100 | * @param management 101 | */ 102 | public void createCompositeIndexes(JanusGraphManagement management) { 103 | /**创建顶点 单个索引**/ 104 | management.buildIndex("byNameIndex", Vertex.class) 105 | .addKey(management.getPropertyKey("name")) 106 | .buildCompositeIndex(); 107 | management.buildIndex("byAgeIndex", Vertex.class) 108 | .addKey(management.getPropertyKey("age")) 109 | .buildCompositeIndex(); 110 | management.buildIndex("byIdIndex", Vertex.class) 111 | .addKey(management.getPropertyKey("id")) 112 | .buildCompositeIndex(); 113 | management.buildIndex("byNoIndex", Vertex.class) 114 | .addKey(management.getPropertyKey("no")) 115 | .buildCompositeIndex(); 116 | management.buildIndex("byAddressIndex", Vertex.class) 117 | .addKey(management.getPropertyKey("address")) 118 | .buildCompositeIndex(); 119 | management.buildIndex("byPlaceIndex", Vertex.class) 120 | .addKey(management.getPropertyKey("place")) 121 | .buildCompositeIndex(); 122 | } 123 | 124 | /** 125 | * 创建混合索引 126 | * 127 | * @param management 128 | */ 129 | public void createMixedIndexes(JanusGraphManagement management) { 130 | if (this.useMixedIndex) { 131 | management.buildIndex("nameAndAgeAndNoAndId", Vertex.class) 132 | .addKey(management.getPropertyKey("name")) 133 | .addKey(management.getPropertyKey("age")) 134 | .addKey(management.getPropertyKey("no")) 135 | .addKey(management.getPropertyKey("id")) 136 | .buildMixedIndex(this.mixedIndexConfigName); 137 | 138 | management.buildIndex("byNANIP", Edge.class) 139 | .addKey(management.getPropertyKey("name")) 140 | .addKey(management.getPropertyKey("age")) 141 | .addKey(management.getPropertyKey("no")) 142 | .addKey(management.getPropertyKey("id")) 143 | .addKey(management.getPropertyKey("place")) 144 | .buildMixedIndex(this.mixedIndexConfigName); 145 | } 146 | 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /src/main/resources/conf/janusgraph-cql-es-server.properties: -------------------------------------------------------------------------------- 1 | # Copyright 2019 JanusGraph Authors 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | gremlin.graph=org.janusgraph.core.JanusGraphFactory 16 | 17 | # JanusGraph configuration sample: Cassandra & Elasticsearch over sockets 18 | # 19 | # This file connects to Cassandra and Elasticsearch services running 20 | # on localhost over the CQL API and the Elasticsearch native 21 | # "Transport" API on their respective default ports. The Cassandra 22 | # and Elasticsearch services must already be running before starting 23 | # JanusGraph with this file. 24 | 25 | # The primary persistence provider used by JanusGraph. This is required. It 26 | # should be set one of JanusGraph's built-in shorthand names for its standard 27 | # storage backends or to the full package and classname of a custom/third-party 28 | # StoreManager implementation. 29 | # 30 | # Default: (no default value) 31 | # Data Type: String 32 | # Mutability: LOCAL 33 | storage.backend=cql 34 | 35 | # The hostname or comma-separated list of hostnames of storage backend 36 | # servers. This is only applicable to some storage backends, such as 37 | # cassandra and hbase. 38 | # 39 | # Default: 127.0.0.1 40 | # Data Type: class java.lang.String[] 41 | # Mutability: LOCAL 42 | 43 | storage.hostname=172.16.2.138 44 | 45 | # The name of JanusGraph's keyspace. It will be created if it does not 46 | # exist. 47 | # 48 | # Default: janusgraph 49 | # Data Type: String 50 | # Mutability: LOCAL 51 | 52 | storage.cql.keyspace=janusgraphtest 53 | 54 | # Whether to enable JanusGraph's database-level cache, which is shared across 55 | # all transactions. Enabling this option speeds up traversals by holding 56 | # hot graph elements in memory, but also increases the likelihood of 57 | # reading stale data. Disabling it forces each transaction to 58 | # independently fetch graph elements from storage before reading/writing 59 | # them. 60 | # 61 | # Default: false 62 | # Data Type: Boolean 63 | # Mutability: MASKABLE 64 | cache.db-cache = true 65 | 66 | # How long, in milliseconds, database-level cache will keep entries after 67 | # flushing them. This option is only useful on distributed storage 68 | # backends that are capable of acknowledging writes without necessarily 69 | # making them immediately visible. 70 | # 71 | # Default: 50 72 | # Data Type: Integer 73 | # Mutability: GLOBAL_OFFLINE 74 | # 75 | # Settings with mutability GLOBAL_OFFLINE are centrally managed in JanusGraph's 76 | # storage backend. After starting the database for the first time, this 77 | # file's copy of this setting is ignored. Use JanusGraph's Management System 78 | # to read or modify this value after bootstrapping. 79 | cache.db-cache-clean-wait = 20 80 | 81 | # Default expiration time, in milliseconds, for entries in the 82 | # database-level cache. Entries are evicted when they reach this age even 83 | # if the cache has room to spare. Set to 0 to disable expiration (cache 84 | # entries live forever or until memory pressure triggers eviction when set 85 | # to 0). 86 | # 87 | # Default: 10000 88 | # Data Type: Long 89 | # Mutability: GLOBAL_OFFLINE 90 | # 91 | # Settings with mutability GLOBAL_OFFLINE are centrally managed in JanusGraph's 92 | # storage backend. After starting the database for the first time, this 93 | # file's copy of this setting is ignored. Use JanusGraph's Management System 94 | # to read or modify this value after bootstrapping. 95 | cache.db-cache-time = 180000 96 | 97 | # Size of JanusGraph's database level cache. Values between 0 and 1 are 98 | # interpreted as a percentage of VM heap, while larger values are 99 | # interpreted as an absolute size in bytes. 100 | # 101 | # Default: 0.3 102 | # Data Type: Double 103 | # Mutability: MASKABLE 104 | cache.db-cache-size = 0.25 105 | 106 | # Connect to an already-running ES instance on localhost 107 | 108 | # The indexing backend used to extend and optimize JanusGraph's query 109 | # functionality. This setting is optional. JanusGraph can use multiple 110 | # heterogeneous index backends. Hence, this option can appear more than 111 | # once, so long as the user-defined name between "index" and "backend" is 112 | # unique among appearances.Similar to the storage backend, this should be 113 | # set to one of JanusGraph's built-in shorthand names for its standard index 114 | # backends (shorthands: lucene, elasticsearch, es, solr) or to the full 115 | # package and classname of a custom/third-party IndexProvider 116 | # implementation. 117 | # 118 | # Default: elasticsearch 119 | # Data Type: String 120 | # Mutability: GLOBAL_OFFLINE 121 | # 122 | # Settings with mutability GLOBAL_OFFLINE are centrally managed in JanusGraph's 123 | # storage backend. After starting the database for the first time, this 124 | # file's copy of this setting is ignored. Use JanusGraph's Management System 125 | # to read or modify this value after bootstrapping. 126 | index.search.backend=elasticsearch 127 | 128 | # The hostname or comma-separated list of hostnames of index backend 129 | # servers. This is only applicable to some index backends, such as 130 | # elasticsearch and solr. 131 | # 132 | # Default: 127.0.0.1 133 | # Data Type: class java.lang.String[] 134 | # Mutability: MASKABLE 135 | index.search.hostname=172.16.2.137 136 | 137 | # The Elasticsearch node.client option is set to this boolean value, and 138 | # the Elasticsearch node.data option is set to the negation of this value. 139 | # True creates a thin client which holds no data. False creates a regular 140 | # Elasticsearch cluster node that may store data. 141 | # 142 | # Default: true 143 | # Data Type: Boolean 144 | # Mutability: GLOBAL_OFFLINE 145 | # 146 | # Settings with mutability GLOBAL_OFFLINE are centrally managed in JanusGraph's 147 | # storage backend. After starting the database for the first time, this 148 | # file's copy of this setting is ignored. Use JanusGraph's Management System 149 | # to read or modify this value after bootstrapping. 150 | index.search.elasticsearch.client-only=true 151 | 152 | # Or start ES inside the JanusGraph JVM 153 | #index.search.backend=elasticsearch 154 | #index.search.directory=db/es 155 | #index.search.elasticsearch.client-only=false 156 | #index.search.elasticsearch.local-mode=true 157 | -------------------------------------------------------------------------------- /src/main/java/com/example/janusgraph/Example/GraphDataLand.java: -------------------------------------------------------------------------------- 1 | package com.example.janusgraph.Example; 2 | 3 | import com.example.janusgraph.config.GraphSourceConfig; 4 | import com.example.janusgraph.config.JanusGraphConfig; 5 | import lombok.extern.log4j.Log4j2; 6 | import org.apache.tinkerpop.gremlin.process.traversal.Bindings; 7 | import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; 8 | import org.apache.tinkerpop.gremlin.structure.Vertex; 9 | import org.janusgraph.core.JanusGraph; 10 | import org.janusgraph.core.schema.JanusGraphManagement; 11 | import org.springframework.beans.factory.annotation.Autowired; 12 | import org.springframework.stereotype.Service; 13 | 14 | /** 15 | * @author 李兵 16 | * @version V1.0 17 | * @description TODO: 图数据添加 18 | * @date 2019/9/5 20:39 19 | */ 20 | @Service 21 | @Log4j2 22 | public class GraphDataLand { 23 | 24 | /** 25 | * used for bindings 26 | */ 27 | private static final String LABEL = "label"; 28 | /** 29 | * 出边 30 | */ 31 | private static final String OUT_V = "outV"; 32 | /** 33 | * 入边 34 | */ 35 | private static final String IN_V = "inV"; 36 | @Autowired 37 | GraphSourceConfig graphSourceConfig; 38 | 39 | @Autowired 40 | JanusGraphConfig janusGraphConfig; 41 | 42 | /** 43 | * 44 | */ 45 | public void createElements1() { 46 | 47 | log.info("creating elements方式1 使用JanusGraphTransaction对象创建"); 48 | JanusGraph graph = janusGraphConfig.graph; 49 | JanusGraphManagement mgt = graph.openManagement(); 50 | /** 51 | * 这里不再写了 参考本工程的GraphOfTheGodsFactory.java 类的load方法。 52 | */ 53 | 54 | } 55 | 56 | 57 | /** 58 | * 59 | */ 60 | public void createElements2(GraphTraversalSource g) { 61 | log.info("creating elements 方式2 使用 GraphTraversalSource 对象创建"); 62 | //java.lang.IllegalArgumentException: The provided key/value array length must be a multiple of two 63 | final Bindings b = Bindings.instance(); 64 | 65 | /************创建人******************/ 66 | Vertex zhangming = g.addV(SchemaVertex.PERSON) 67 | .property(SchemaProperties.NAME, "张明", 68 | SchemaProperties.NAME, "小明", 69 | SchemaProperties.NAME, "明明", 70 | SchemaProperties.NAME, "小张", 71 | SchemaProperties.AGE, 30, 72 | SchemaProperties.GENDER, "男", 73 | SchemaProperties.NO, "11111111111111111", 74 | SchemaProperties.PHONE, "1351111111", 75 | SchemaProperties.TIME, "2019年2月1号", 76 | SchemaProperties.ID, "0111") 77 | .next(); 78 | 79 | Vertex zhaoshi = g.addV(SchemaVertex.PERSON) 80 | .property(SchemaProperties.NAME, "赵四", 81 | SchemaProperties.NAME, "小赵", 82 | SchemaProperties.AGE, 29, 83 | SchemaProperties.GENDER, "男", 84 | SchemaProperties.NO, "222222222222222222", 85 | SchemaProperties.PHONE, "13522222222", 86 | SchemaProperties.TIME, "2019年2月2号", 87 | SchemaProperties.ID, "0222") 88 | .next(); 89 | 90 | Vertex wanglei = g.addV(SchemaVertex.PERSON) 91 | .property(SchemaProperties.NAME, "王磊", SchemaProperties.NAME, "小王", 92 | SchemaProperties.AGE, 28, 93 | SchemaProperties.GENDER, "男", 94 | SchemaProperties.NO, "333333333333333333", 95 | SchemaProperties.PHONE, "13533333333", 96 | SchemaProperties.TIME, "2019年2月3号", 97 | SchemaProperties.ID, "0333") 98 | .next(); 99 | 100 | Vertex lixin = g.addV(SchemaVertex.PERSON) 101 | .property(SchemaProperties.NAME, "李欣" 102 | , SchemaProperties.AGE, 21 103 | , SchemaProperties.GENDER, "女" 104 | , SchemaProperties.NO, "4444444444444444" 105 | , SchemaProperties.PHONE, "13544444444" 106 | , SchemaProperties.TIME, "2019年2月4号" 107 | , SchemaProperties.ID, "0444") 108 | .next(); 109 | 110 | Vertex liyan = g.addV(SchemaVertex.PERSON) 111 | .property(SchemaProperties.NAME, "李艳" 112 | , SchemaProperties.AGE, 22 113 | , SchemaProperties.GENDER, "女" 114 | , SchemaProperties.NO, "55555555555555555" 115 | , SchemaProperties.PHONE, "1355555555" 116 | , SchemaProperties.TIME, "2019年2月5号" 117 | , SchemaProperties.ID, "0555") 118 | .next(); 119 | 120 | 121 | Vertex zhangxin = g.addV(SchemaVertex.PERSON) 122 | .property(SchemaProperties.NAME, "张鑫" 123 | , SchemaProperties.AGE, 39 124 | , SchemaProperties.GENDER, "女" 125 | , SchemaProperties.NO, "66666666666666666" 126 | , SchemaProperties.PHONE, "136666666666" 127 | , SchemaProperties.ID, "0666") 128 | .next(); 129 | Vertex zhanghan = g.addV(SchemaVertex.PERSON) 130 | .property(SchemaProperties.NAME, "张翰" 131 | , SchemaProperties.AGE, 45 132 | , SchemaProperties.GENDER, "男" 133 | , SchemaProperties.NO, "7777777777777777" 134 | , SchemaProperties.PHONE, "137777777777" 135 | , SchemaProperties.ID, "0777") 136 | .next(); 137 | 138 | 139 | /******创建公司*******/ 140 | Vertex apple = g.addV(SchemaVertex.COMPANY) 141 | .property(SchemaProperties.NAME, "苹果科技公司" 142 | , SchemaProperties.PHONE, "010-11111111" 143 | , SchemaProperties.ID, "1111" 144 | , SchemaProperties.PLACE, b.of(SchemaProperties.PLACE, getGeoFloatArray(37.7f, 23.9f))) 145 | .next(); 146 | 147 | 148 | Vertex ibm = g.addV(SchemaVertex.COMPANY) 149 | .property(SchemaProperties.NAME, "IMD公司" 150 | , SchemaProperties.PHONE, "010-22222222" 151 | , SchemaProperties.ID, "1222" 152 | , SchemaProperties.PLACE, b.of(SchemaProperties.PLACE, getGeoFloatArray(39.2f, 26.6f))) 153 | .next(); 154 | 155 | /*****创建地点*******/ 156 | Vertex adrs1 = g.addV(SchemaVertex.LOCALHOST) 157 | .property(SchemaProperties.NAME, "洛克时代" 158 | , SchemaProperties.ADDRESS, "北京市朝阳区慧忠里13号" 159 | , SchemaProperties.ID, "3111" 160 | , SchemaProperties.PLACE, getGeoFloatArray(26.9f, 21.1f)) 161 | .next(); 162 | Vertex adrs2 = g.addV(SchemaVertex.LOCALHOST) 163 | .property(SchemaProperties.NAME, "软件园" 164 | , SchemaProperties.ADDRESS, "北京市海淀区西二旗" 165 | , SchemaProperties.ID, "3222" 166 | , SchemaProperties.PLACE, getGeoFloatArray(28.3f, 39.6f)) 167 | .next(); 168 | 169 | /** 创建点与点的关系 */ 170 | 171 | g.V(zhangming).as("a").V(zhanghan).addE("father").from("a").next(); 172 | g.V(zhangming).as("a").V(zhangxin).addE("mother").from("a").next(); 173 | g.V(zhangming).as("a").V(zhaoshi).addE("brother").from("a").next(); 174 | g.V(zhangming).as("a").V(apple).addE("belong").from("a").next(); 175 | 176 | g.V(zhaoshi).as("a").V(zhanghan).addE("father").from("a").next(); 177 | g.V(zhaoshi).as("a").V(zhangxin).addE("mother").from("a").next(); 178 | g.V(zhaoshi).as("a").V(zhangming).addE("brother").from("a").next(); 179 | g.V(zhaoshi).as("a").V(apple).addE("belong").from("a").next(); 180 | 181 | 182 | g.V(wanglei).as("a").V(zhaoshi).addE("brother").from("a").next(); 183 | g.V(wanglei).as("a").V(apple).addE("belong").from("a").next(); 184 | 185 | g.V(lixin).as("a").V(ibm).addE("belong").from("a").next(); 186 | g.V(lixin).as("a").V(liyan).addE("brother").from("a").next(); 187 | 188 | g.V(liyan).as("a").V(lixin).addE("brother").from("a").next(); 189 | g.V(liyan).as("a").V(apple).addE("belong").from("a").next(); 190 | 191 | 192 | g.V(apple).as("a").V(adrs1).addE("belong").from("a").next(); 193 | g.V(ibm).as("a").V(adrs2).addE("belong").from("a").next(); 194 | } 195 | 196 | protected float[] getGeoFloatArray(float lat, float lon) { 197 | float[] fa = new float[]{lat, lon}; 198 | return fa; 199 | } 200 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # janusgraph-dome 2 | 这是一个基于Java-maven创建的的Janus graph 0.4.0版本示例程序,及遇到的问题。这里我们不做过多的介绍,因为用到的组件比较多,你想要了解那种就去它的官网进行文档阅读。本项目主要介绍Java操作。 3 | 4 | ## 介绍 ## 5 |   JanusGraph(以下都是官网抄的,我们只需要知道支持那种组件就行)是一个开源的分布式图数据库。它具有很好的扩展性,通过多机集群可支持存储和查询数百亿的顶点和边的图数据。JanusGraph是一个事务数据库,支持大量用户高并发地执行复杂的实时图遍历。 6 |   JanusGraph旨在支持图形处理,以至于它们需要超出单个机器所能提供的存储和计算能力。实时遍历和分析查询的缩放图数据处理是JanusGraph的基本优势。。 7 | 8 | **它提供了如下特性**: 9 | 10 | - 支持数据和用户增长的弹性和线性扩展; 11 | - 通过数据分发和复制来提过性能和容错; 12 | - 支持多数据中心的高可用和热备份; 13 | - 支持ACID 和最终一致性; 14 | - 支持多种后端存储: 15 | 1. **Apache Cassandr** 16 | 2. **Apache HBase** 17 | 3. **Google Cloud Bigtable** 18 | 4. **Oracle BerkeleyDB(仅供测试环境)** 19 | - 支持全局的图数据分析,报表以及和如下大数据平台的ETL集成: 20 | 1. **Apache Spark** 21 | 2. **Apache Giraph** 22 | 3. **Apache Hadoop** 23 | - 支持geo, 数值范围以及通过如下工具进行全文检索: 24 | 1. **ElasticSearch** 25 | 2. **Apache Solr** 26 | 3. **Apache Lucene** 27 | - 支持与Apache TinkerPop图栈进行原生集成: 28 | 1. **Gremlin 图查询语言** 29 | 2. **Gremlin 图服务器** 30 | 3. **Gremlin 应用** 31 | - 在Apache 2 license下开源可以通过如下工具来可视化存储在JanusGraph中的图数据: 32 | 1. **Cytoscape** 33 | 2. **Apache TinkerPop的Gephi插件** 34 | 3. **Graphexp KeyLines by Cambridge Intelligence** 35 | 4. **Linkurious** 36 | 37 | **用到的链接** 38 | >-- 官网地址:[官网](https://janusgraph.org/) 39 | >-- 官网文档:[文档](https://docs.janusgraph.org/) 40 | >-- 源码网址: [GitHub](https://github.com/JanusGraph/janusgraph) 41 | >-- 搭建形式:[官网](https://docs.janusgraph.org/basics/deployment/) 42 | >-- Java-API:[官网](https://javadoc.io/doc/org.janusgraph/janusgraph-core/0.4.0) 43 | > 44 | >-- 数据存储: 45 | >>[Apache Cassandra](https://docs.janusgraph.org/latest/cassandra.html) 46 | >>[Apache HBaseracle](https://docs.janusgraph.org/latest/hbase.html) 47 | >>[Berkeley DB Java版](https://docs.janusgraph.org/latest/bdb.html) 48 | > 49 | >--指数,加速并启用更复杂的查询: 50 | >>[Elasticsearch](https://docs.janusgraph.org/latest/elasticsearch.html) 51 | >>[Apache Solr](https://docs.janusgraph.org/latest/solr.html) 52 | >>[Apache Lucene](https://docs.janusgraph.org/latest/lucene.html) 53 | > 54 | >--查询语言: 55 | >>[tinkerpop-Gremlin](http://tinkerpop.apache.org/docs/3.4.1/reference/#tail-step) 56 | 57 | ## 基础环境及组件 ## 58 | Janus graph可以在Linux系统或window系统下运行,两种方式运行.bat/.sh 两种文件即可。 59 | 本项目基于centos7系统,Cassandra 单机,Elasticsearch 单机。我们这里为的是学习,组件越多问题越多,越不好排查, 60 | 当使用熟练了可以进行集群,集群也很简单参考集[链接](https://github.com/bingbingll/janusgraph-dome/blob/master/集群搭建.md)。 61 | 这里需要你看下版本[兼容](https://docs.janusgraph.org/changelog/): 62 | 63 | 1. centos7.x 64 | 1. 注意:先关闭防火墙-[防火墙参考](https://www.cnblogs.com/yyxq/p/10551274.html) 65 | 2. Java Oracle-Java-1.8或openJava-1.8 66 | 3. 安装必要软件 67 | 1. 安装jdk: `yum install java -y` 68 | 2. 安装zip: `yum install -y unzip zip` 69 | 4. 服务器最好是2台以上;我这里是172.16.2.137、172.16.2.138。 70 | 3. 下载Cassandra 上传至172.16.2.138 并解压 71 | 1. 启动: 后台启动->`bin/cassandra -R` 前台启动-> `./cassandra` 72 | 2. 停止:`pgrep -f CassandraDaemon` `kill -9 [进程号]` 73 | 4. 下载Elasticsearch。出于安全原因,Elasticsearch必须在非root帐户下运行,所以需要手动添加用户进行启动脚本如下: 74 | 1. root 用户创建用户命令:`groupadd es;`、`useradd es -g es -p es;`、`chown -R es:es elasticsearch` 这一句要在es所在的上级目录执行。 75 | 2. centos需要修改以下参数;root 用户下 修改配置文件 `vi /etc/security/limits.conf` 最后一行增加 `* soft nofile 65536 * hard nofile 131072` ,保存退出后,在修改 `vi /etc/sysctl.conf` 最后一行追加 `vm.max_map_count=655360` 然后保存退出,执行 `sysctl -p` 76 | 3. 后台启动: ./elastic -d 77 | 4. 停止:ps -ef | grep elastic kill -9 [进程号] 78 | 79 | ## 服务运行 ## 80 | 登录centos系统,进入janusgraph-0.4.0-hadoop2/conf/gremlin-server 文件夹目录修改文件如下: 81 | 82 | 1. 服务式启动(Java程序调用必须启动) 83 | - gremlin-server.yaml 84 | - `host: 172.16.2.13` janusgraph所在的服务器IP,这样就可以在其他电脑上访问到了 85 | - `channelizer: org.apache.tinkerpop.gremlin.server.channel.WsAndHttpChannelizer` 支持websocket和http 86 | - janusgraph-cql-es-server.properties 87 | - `storage.hostname=172.16.2.138` 数据库所在的服务器IP,多个IP用,号隔开 88 | - `storage.cql.keyspace=janusgraphtest` 自定义库名称 89 | - `index.search.backend=elasticsearch` es无需改动 90 | - `index.search.hostname=127.0.0.1` 使用的是自带的无需改动,若是有别的es改位其IP即可,多个IP用,号隔开 91 | - 上面两个文件改完后保存,然后cd到/janusgraph-0.4.0-hadoop2/bin目录 92 | 输入 `nohup ./gremlin-server.sh conf/gremlin-server/gremlin-server.yaml` 后台启动。 93 | 94 | 95 | 96 | 2. 控制台式启动(主要用于控制台查看学习用) 97 | - 启动 Gremlin Console:./gremlin.sh 启动控制台命令 98 | - 开启一个图数据库实例:gremlin> graph = JanusGraphFactory.open('conf/janusgraph-cql-es.properties');注意这里的配置文件内容要和conf/gremlin-server/janusgraph-cql-es-server.properties的内容一致 99 | - 获取管理对象:gremlin> mgmt = graph.openManagement() 100 | - 查看所有的顶点标签: gremlin> labels = mgmt.getVertexLabels() 101 | - ==>user 102 | ==>statusUpdate 103 | - 查看所有的边:mgmt.getRelationTypes(EdgeLabel.class) 104 | - ==>posts 105 | ==>follows 106 | ==>works 107 | ==>follow 108 | ==>mother 109 | - 根据主键查看属性:mgmt.getPropertyKey('marcelocf.janusgraph.userName') 110 | - ==>marcelocf.janusgraph.userName 111 | - 获取图遍历句柄:gremlin> g = graph.traversal() 112 | 113 | ## Java代码编写 ## 114 | 项目下载后需要你修改 项目的conf/gremlin.remote.driver.clusterFile属性的路径值 115 | 116 | ### schema 介绍 117 |   首先这里需要先了解一下Janus graph中schema的概念,若是schema概念没弄明白后续也就没法学习及应用了。 118 | 若您的英语很好可以先在官网文档-[链接](https://docs.janusgraph.org/basics/schema/)-中对于schema的阐述进行了解(反正我只是看个大概脑子稀里糊涂的)。 119 | 还可以参考[链接](https://www.cnblogs.com/jiyuqi/p/7127178.html?utm_source=itdadao&utm_medium=referral) 介绍。 120 | 121 |   官网文档说到**The schema type - i.e. edge label, property key,or vertex label - is assigned to elements in the graph - i.e. edge, properties or vertices respectively - when they are first created. The assigned schema type cannot be changed for a particular element. This ensures a stable type system that is easy to reason about.** 什么意思呢?根据我的理解,schema(模型)!用于定义一个图中的数据是什么样子(换句话说就是框定数据格式),数据依据此定义进行数据制作从而完成一个图。因此创建schema(模型)时需要先定义图中顶点(vertex)、边(edge)和属性(property)然后才能组成一个schema。在图逻辑中,vertex描述为每个单独的顶点数据类型是什么(可以理解为抽象出来的一个类,例如人,公司,地点等等),edge作为连接图中2个以上的vertex的桥梁,描述图中vertex(顶点)与vertex(顶点)之间的存在的关系,而property(属性)依附在vertex或edge上,填充顶点或边的属性。换句话说:我们在关系型数据库中定义一个实体表时;要给这个表设定一个表名,列名及列的类型,值是否为空,是否为主键等。这和我们定义一个schema是一个概念!这样说同学你是否豁然开朗呢? 122 | 123 |   在引用官网的一句话**Each JanusGraph graph has a schema comprised of the edge labels, property keys, and vertex labels used therein. A JanusGraph schema can either be explicitly or implicitly defined. Users are encouraged to explicitly define the graph schema during application development. An explicitly defined schema is an important component of a robust graph application and greatly improves collaborative software development. Note, that a JanusGraph schema can be evolved over time without any interruption of normal database operations. Extending the schema does not slow down query answering and does not require database downtime.** 每一个图都有一个schema,schema中的数据是由**边标签、属性键、顶点标签**组成,在创建schema时可以显示地定义(就是通过配置文件或Java定义变量)schema(图)的三个元素,也可以隐式定义,鼓励用户在应用程序开发期间显式定义图形模式。隐式定义方式通过g对象创建、通过http服务式创建等。可以参考本工程的com.example.janusgraph.referenceExample目录下的GraphOfTheGodsFactory.java和RemoteGraphApp.java 或 RemoteGraphApp.java 继承的JanusGraphApp.class 进行深刻理解,然后根据你所在的业务场景进行选择。 124 | 125 | ### 创建schema 126 | 可以根据[schema 介绍](https://github.com/bingbingll/janusgraph-example#schema-介绍)这个节点的几个类进行编写,这里我选择JanusGraphApp.class 编写形式。为什么呢?原因为操作 JanusGraph有两套 API, 127 | 分别是 Graph Structure(结构) 和 Graph Process(处理)。 建议只用 graph Structure来做图的模型定义及数据库管理相关操作。 128 | 图的数据操作,包括创建、更新、删除及遍历都用 g( Graph Process)来操作。如果想用 API 来大批量地操作数据,可以跳过 JanusGraph,直接写入后端存储。 129 | 创建schema参考本工程的[CreateSchema.java](https://github.com/bingbingll/janusgraph-example/blob/master/src/main/java/com/example/janusgraph/Example/CreateSchema.java); 130 | 图数据写入参考本工程的[GraphDataLand.java](https://github.com/bingbingll/janusgraph-example/blob/master/src/main/java/com/example/janusgraph/Example/GraphDataLand.java) 131 | 测试类:[ExamplTest](https://github.com/bingbingll/janusgraph-example/blob/master/src/test/java/com/example/janusgraph/ExamplTest.java) 132 | ### 数据据展示 133 | 我们使用graphexp进行页面展示,使用nginx作为web服务器。 134 | 1. 下载graphexp-[链接](https://github.com/bricaud/graphexp)源码,修改 graphexp.html中的,将 localhost改为Janus graph的IP地址。 135 | 然后将源码上传到/opt 目录下。 136 | 2. 安装并配置nginx如下: 137 | ``` 138 | server { 139 | listen 8083; 140 | server_name 172.16.2.137; 141 | index index.html; 142 | location / { 143 | root /opt/graphexp; 144 | } 145 | } 146 | ``` 147 | 然后启动或重启nginx 148 | 3. 浏览器中访问 149 | - 访问 http://172.16.2.137:8083/graphexp.html 点击”Get graphinfo”按钮,可以获取到 JanusGraph中的图数据。点击右上角“Search”按钮检索出图 150 | - 加载罗马诸神图 为了更好地展示图的效果,通过 Gremlin Console加载 gremlin>:remoteconnect tinkerpop.serverconf/remote.yaml 151 | 152 | 153 | ### 错误总结 154 | 1. java.lang.IllegalArgumentException: The provided key/value array length must be a multiple of two。可能是键值没有匹配上或书写错误。 155 | 2. Caused by: io.netty.handler.codec.DecoderException: org.apache.tinkerpop.gremlin.driver.ser.SerializationException: org.apache.tinkerpop.shaded.kryo.KryoException: Encountered unregistered class ID: 65536 156 | 解决办法:https://github.com/orientechnologies/orientdb-gremlin/issues/161 或 https://stackoverflow.com/questions/53202745/janusgraph-0-3-0-tinkerpop-3-3-3-java-serialization-error-after-adding-edge-us 157 | -------------------------------------------------------------------------------- /src/main/java/com/example/janusgraph/referenceExample/GraphOfTheGodsFactory.java: -------------------------------------------------------------------------------- 1 | package com.example.janusgraph.referenceExample; 2 | 3 | import com.google.common.base.Preconditions; 4 | import org.apache.tinkerpop.gremlin.process.traversal.Order; 5 | import org.apache.tinkerpop.gremlin.structure.Direction; 6 | import org.apache.tinkerpop.gremlin.structure.Edge; 7 | import org.apache.tinkerpop.gremlin.structure.T; 8 | import org.apache.tinkerpop.gremlin.structure.Vertex; 9 | import org.janusgraph.core.*; 10 | import org.janusgraph.core.attribute.Geoshape; 11 | import org.janusgraph.core.schema.ConsistencyModifier; 12 | import org.janusgraph.core.schema.JanusGraphIndex; 13 | import org.janusgraph.core.schema.JanusGraphManagement; 14 | import org.janusgraph.graphdb.database.StandardJanusGraph; 15 | import org.springframework.beans.factory.annotation.Configurable; 16 | 17 | @Configurable 18 | public class GraphOfTheGodsFactory { 19 | public static final String INDEX_NAME = "search"; 20 | private static final String ERR_NO_INDEXING_BACKEND = 21 | "The indexing backend with name \"%s\" is not defined. Specify an existing indexing backend or " + 22 | "use GraphOfTheGodsFactory.loadWithoutMixedIndex(graph,true) to load without the use of an " + 23 | "indexing backend."; 24 | 25 | public static JanusGraph create(final String directory) { 26 | JanusGraphFactory.Builder config = JanusGraphFactory.build(); 27 | config.set("storage.backend", "berkeleyje"); 28 | config.set("storage.directory", directory); 29 | config.set("index." + INDEX_NAME + ".backend", "elasticsearch"); 30 | 31 | JanusGraph graph = config.open(); 32 | GraphOfTheGodsFactory.load(graph); 33 | return graph; 34 | } 35 | 36 | public static void loadWithoutMixedIndex(final JanusGraph graph, boolean uniqueNameCompositeIndex) { 37 | load(graph, null, uniqueNameCompositeIndex); 38 | } 39 | 40 | public static void load(final JanusGraph graph) { 41 | load(graph, INDEX_NAME, true); 42 | } 43 | 44 | private static boolean mixedIndexNullOrExists(StandardJanusGraph graph, String indexName) { 45 | return indexName == null || graph.getIndexSerializer().containsIndex(indexName); 46 | } 47 | 48 | public static void load(final JanusGraph graph, String mixedIndexName, boolean uniqueNameCompositeIndex) { 49 | if (graph instanceof StandardJanusGraph) { 50 | Preconditions.checkState(mixedIndexNullOrExists((StandardJanusGraph) graph, mixedIndexName), 51 | ERR_NO_INDEXING_BACKEND, mixedIndexName); 52 | } 53 | 54 | //Create Schema 55 | JanusGraphManagement management = graph.openManagement(); 56 | 57 | /**定义属性 Property Keys**/ 58 | final PropertyKey name = management.makePropertyKey("name").dataType(String.class).make(); 59 | JanusGraphManagement.IndexBuilder nameIndexBuilder = management.buildIndex("name", Vertex.class).addKey(name); 60 | if (uniqueNameCompositeIndex) 61 | nameIndexBuilder.unique(); 62 | JanusGraphIndex nameIndex = nameIndexBuilder.buildCompositeIndex(); 63 | management.setConsistency(nameIndex, ConsistencyModifier.LOCK); 64 | 65 | final PropertyKey age = management.makePropertyKey("age").dataType(Integer.class).make(); 66 | if (null != mixedIndexName) 67 | management.buildIndex("vertices", Vertex.class).addKey(age).buildMixedIndex(mixedIndexName); 68 | //时间 69 | final PropertyKey time = management.makePropertyKey("time").dataType(Integer.class).make(); 70 | //原因 71 | final PropertyKey reason = management.makePropertyKey("reason").dataType(String.class).make(); 72 | //地点,地方,位置 73 | final PropertyKey place = management.makePropertyKey("place").dataType(Geoshape.class).make(); 74 | if (null != mixedIndexName) 75 | management.buildIndex("edges", Edge.class).addKey(reason).addKey(place).buildMixedIndex(mixedIndexName); 76 | 77 | /**定义边Edge Labels**/ 78 | //父亲 79 | management.makeEdgeLabel("father").multiplicity(Multiplicity.MANY2ONE).make(); 80 | //母亲 81 | management.makeEdgeLabel("mother").multiplicity(Multiplicity.MANY2ONE).make(); 82 | //作战 83 | EdgeLabel battled = management.makeEdgeLabel("battled").signature(time).make(); 84 | //给这个边创建索引 85 | management.buildEdgeIndex(battled, "battlesByTime", Direction.BOTH, Order.desc, time); 86 | //生活生命 87 | management.makeEdgeLabel("lives").signature(reason).make(); 88 | // 宠物 89 | management.makeEdgeLabel("pet").make(); 90 | // 兄弟 91 | management.makeEdgeLabel("brother").make(); 92 | 93 | /**定义顶点 Vertex Lables 相当于顶一个类型*/ 94 | management.makeVertexLabel("titan").make(); // 95 | management.makeVertexLabel("location").make(); //地点 96 | management.makeVertexLabel("god").make(); //神 97 | management.makeVertexLabel("demigod").make(); //半神 98 | management.makeVertexLabel("human").make(); //人 99 | management.makeVertexLabel("monster").make(); // 怪物 100 | //提交 101 | management.commit(); 102 | /**Schema 创建完成**/ 103 | 104 | 105 | JanusGraphTransaction tx = graph.newTransaction(); 106 | // vertices 107 | //创建一个name为saturn的顶点所属类型(标签)为titan 年龄为10000 108 | Vertex saturn = tx.addVertex(T.label, "titan", "name", "saturn", "age", 10000); 109 | Vertex sky = tx.addVertex(T.label, "location", "name", "sky"); 110 | Vertex sea = tx.addVertex(T.label, "location", "name", "sea"); 111 | //创建一个名为jupiter(木星)所属类型为god年龄为5000 112 | Vertex jupiter = tx.addVertex(T.label, "god", "name", "jupiter", "age", 5000); 113 | Vertex neptune = tx.addVertex(T.label, "god", "name", "neptune", "age", 4500); 114 | Vertex hercules = tx.addVertex(T.label, "demigod", "name", "hercules", "age", 30); 115 | Vertex alcmene = tx.addVertex(T.label, "human", "name", "alcmene", "age", 45); 116 | Vertex pluto = tx.addVertex(T.label, "god", "name", "pluto", "age", 4000); 117 | Vertex nemean = tx.addVertex(T.label, "monster", "name", "nemean"); 118 | Vertex hydra = tx.addVertex(T.label, "monster", "name", "hydra"); 119 | Vertex cerberus = tx.addVertex(T.label, "monster", "name", "cerberus"); 120 | Vertex tartarus = tx.addVertex(T.label, "location", "name", "tartarus"); 121 | 122 | // edges 123 | //为jupiter(木星)添加边及边的属性 124 | //木星的父亲是Saturn(土星) 125 | jupiter.addEdge("father", saturn); 126 | //木星生活账sky,原因是 的生活喜欢清新的微风 127 | jupiter.addEdge("lives", sky, "reason", "loves fresh breezes"); 128 | //木星的兄弟是 海王星 129 | jupiter.addEdge("brother", neptune); 130 | //木星的另一个兄弟为冥王星 131 | jupiter.addEdge("brother", pluto); 132 | 133 | //为neptune(海王星) 添加边及边的属性 134 | //海王星生活中海中原因是他喜欢波浪 135 | neptune.addEdge("lives", sea).property("reason", "loves waves"); 136 | //海王星的兄弟是 木星 137 | neptune.addEdge("brother", jupiter); 138 | //海王星的另一个兄弟是冥王星 139 | neptune.addEdge("brother", pluto); 140 | 141 | //为hercules(大力神)添加边及边的属性 142 | hercules.addEdge("father", jupiter); 143 | hercules.addEdge("mother", alcmene); 144 | hercules.addEdge("battled", nemean, "time", 1, "place", Geoshape.point(38.1f, 23.7f)); 145 | hercules.addEdge("battled", hydra, "time", 2, "place", Geoshape.point(37.7f, 23.9f)); 146 | hercules.addEdge("battled", cerberus, "time", 12, "place", Geoshape.point(39f, 22f)); 147 | 148 | //为pluto(冥王星)添加边及边的属性 149 | pluto.addEdge("brother", jupiter); 150 | pluto.addEdge("brother", neptune); 151 | pluto.addEdge("lives", tartarus, "reason", "no fear of death"); 152 | pluto.addEdge("pet", cerberus); 153 | 154 | //为地狱狗添加边 155 | //生活在塔耳塔洛斯 156 | cerberus.addEdge("lives", tartarus); 157 | 158 | // commit the transaction to disk 159 | tx.commit(); 160 | } 161 | 162 | /** 163 | * Calls {@link JanusGraphFactory#open(String)}, passing the JanusGraph configuration file path 164 | * which must be the sole element in the {@code args} array, then calls 165 | * {@link #load(JanusGraph)} on the opened graph, 166 | * then calls {@link JanusGraph#close()} 167 | * and returns. 168 | *

169 | * This method may call {@link System#exit(int)} if it encounters an error, such as 170 | * failure to parse its arguments. Only use this method when executing main from 171 | * a command line. Use one of the other methods on this class ({@link #create(String)} 172 | * or {@link #load(JanusGraph)}) when calling from 173 | * an enclosing application. 174 | * 175 | * @param args a singleton array containing a path to a JanusGraph config properties file 176 | */ 177 | public static void main(String args[]) { 178 | if (null == args || 1 != args.length) { 179 | System.err.println("Usage: GraphOfTheGodsFactory "); 180 | System.exit(1); 181 | } 182 | 183 | JanusGraph g = JanusGraphFactory.open(args[0]); 184 | load(g); 185 | g.close(); 186 | } 187 | } 188 | -------------------------------------------------------------------------------- /src/main/java/com/example/janusgraph/referenceExample/RemoteGraphApp.java: -------------------------------------------------------------------------------- 1 | package com.example.janusgraph.referenceExample; 2 | 3 | import org.apache.commons.configuration.Configuration; 4 | import org.apache.commons.configuration.ConfigurationException; 5 | import org.apache.commons.configuration.PropertiesConfiguration; 6 | import org.apache.tinkerpop.gremlin.driver.Client; 7 | import org.apache.tinkerpop.gremlin.driver.Cluster; 8 | import org.apache.tinkerpop.gremlin.driver.Result; 9 | import org.apache.tinkerpop.gremlin.driver.ResultSet; 10 | import org.apache.tinkerpop.gremlin.process.traversal.Bindings; 11 | import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; 12 | import org.apache.tinkerpop.gremlin.structure.Vertex; 13 | import org.apache.tinkerpop.gremlin.structure.util.empty.EmptyGraph; 14 | import org.janusgraph.core.JanusGraph; 15 | import org.janusgraph.core.attribute.Geoshape; 16 | import org.janusgraph.example.JanusGraphApp; 17 | import org.slf4j.Logger; 18 | import org.slf4j.LoggerFactory; 19 | 20 | import java.util.stream.Stream; 21 | 22 | ; 23 | 24 | /** 25 | * @author 李兵 26 | * @version V1.0 27 | * @description TODO: 28 | * @date 2019/8/30 18:13 29 | */ 30 | public class RemoteGraphApp extends JanusGraphApp { 31 | private static final Logger LOGGER = LoggerFactory.getLogger(RemoteGraphApp.class); 32 | 33 | // used for bindings 34 | private static final String NAME = "name"; 35 | private static final String AGE = "age"; 36 | private static final String TIME = "time"; 37 | private static final String REASON = "reason"; 38 | private static final String PLACE = "place"; 39 | private static final String LABEL = "label"; 40 | private static final String OUT_V = "outV"; 41 | private static final String IN_V = "inV"; 42 | 43 | protected JanusGraph janusgraph; 44 | protected Cluster cluster; 45 | protected Client client; 46 | protected Configuration conf; 47 | 48 | /** 49 | * Constructs a graph app using the given properties. 50 | * 51 | * @param fileName location of the properties file 52 | */ 53 | public RemoteGraphApp(final String fileName) { 54 | super(fileName); 55 | // the server auto-commits per request, so the application code doesn't 56 | // need to explicitly commit transactions 57 | this.supportsTransactions = false; 58 | } 59 | 60 | public static void main(String[] args) { 61 | final String fileName = (args != null && args.length > 0) ? args[0] : null; 62 | final RemoteGraphApp app = new RemoteGraphApp(fileName); 63 | app.runApp(); 64 | } 65 | 66 | @Override 67 | public GraphTraversalSource openGraph() throws ConfigurationException { 68 | LOGGER.info("opening graph"); 69 | conf = new PropertiesConfiguration(propFileName); 70 | 71 | // using the remote driver for schema 72 | try { 73 | cluster = Cluster.open(conf.getString("gremlin.remote.driver.clusterFile")); 74 | client = cluster.connect(); 75 | } catch (Exception e) { 76 | throw new ConfigurationException(e); 77 | } 78 | 79 | // using the remote graph for queries 80 | graph = EmptyGraph.instance(); 81 | 82 | g = graph.traversal().withRemote(conf); 83 | return g; 84 | } 85 | 86 | @Override 87 | public void createElements() { 88 | LOGGER.info("creating elements"); 89 | 90 | // Use bindings to allow the Gremlin Server to cache traversals that 91 | // will be reused with different parameters. This minimizes the 92 | // number of scripts that need to be compiled and cached on the server. 93 | // https://tinkerpop.apache.org/docs/3.2.6/reference/#parameterized-scripts 94 | final Bindings b = Bindings.instance(); 95 | 96 | // see GraphOfTheGodsFactory.java 97 | 98 | Vertex saturn = g.addV(b.of(LABEL, "titan")) 99 | .property(NAME, b.of(NAME, "saturn")) 100 | .property(AGE, b.of(AGE, 10000)).next(); 101 | Vertex sky = g.addV(b.of(LABEL, "location")).property(NAME, b.of(NAME, "sky")).next(); 102 | Vertex sea = g.addV(b.of(LABEL, "location")).property(NAME, b.of(NAME, "sea")).next(); 103 | Vertex jupiter = g.addV(b.of(LABEL, "god")).property(NAME, b.of(NAME, "jupiter")).property(AGE, b.of(AGE, 5000)) 104 | .next(); 105 | Vertex neptune = g.addV(b.of(LABEL, "god")).property(NAME, b.of(NAME, "neptune")).property(AGE, b.of(AGE, 4500)) 106 | .next(); 107 | Vertex hercules = g.addV(b.of(LABEL, "demigod")).property(NAME, b.of(NAME, "hercules")) 108 | .property(AGE, b.of(AGE, 30)).next(); 109 | Vertex alcmene = g.addV(b.of(LABEL, "human")).property(NAME, b.of(NAME, "alcmene")).property(AGE, b.of(AGE, 45)) 110 | .next(); 111 | Vertex pluto = g.addV(b.of(LABEL, "god")).property(NAME, b.of(NAME, "pluto")).property(AGE, b.of(AGE, 4000)) 112 | .next(); 113 | Vertex nemean = g.addV(b.of(LABEL, "monster")).property(NAME, b.of(NAME, "nemean")).next(); 114 | Vertex hydra = g.addV(b.of(LABEL, "monster")).property(NAME, b.of(NAME, "hydra")).next(); 115 | Vertex cerberus = g.addV(b.of(LABEL, "monster")).property(NAME, b.of(NAME, "cerberus")).next(); 116 | Vertex tartarus = g.addV(b.of(LABEL, "location")).property(NAME, b.of(NAME, "tartarus")).next(); 117 | 118 | g.V(b.of(OUT_V, jupiter)).as("a") //木星出边 119 | .V(b.of(IN_V, saturn)) //土星入边 120 | .addE(b.of(LABEL, "father")) //定义关系为父亲 121 | .from("a").next(); //数据提交 122 | 123 | g.V(b.of(OUT_V, jupiter)).as("a").V(b.of(IN_V, sky)).addE(b.of(LABEL, "lives")) 124 | .property(REASON, b.of(REASON, "loves fresh breezes")).from("a").next(); 125 | g.V(b.of(OUT_V, jupiter)).as("a").V(b.of(IN_V, neptune)).addE(b.of(LABEL, "brother")).from("a").next(); 126 | g.V(b.of(OUT_V, jupiter)).as("a").V(b.of(IN_V, pluto)).addE(b.of(LABEL, "brother")).from("a").next(); 127 | 128 | g.V(b.of(OUT_V, neptune)).as("a").V(b.of(IN_V, sea)).addE(b.of(LABEL, "lives")) 129 | .property(REASON, b.of(REASON, "loves waves")).from("a").next(); 130 | g.V(b.of(OUT_V, neptune)).as("a").V(b.of(IN_V, jupiter)).addE(b.of(LABEL, "brother")).from("a").next(); 131 | g.V(b.of(OUT_V, neptune)).as("a").V(b.of(IN_V, pluto)).addE(b.of(LABEL, "brother")).from("a").next(); 132 | 133 | g.V(b.of(OUT_V, hercules)).as("a").V(b.of(IN_V, jupiter)).addE(b.of(LABEL, "father")).from("a").next(); 134 | g.V(b.of(OUT_V, hercules)).as("a").V(b.of(IN_V, alcmene)).addE(b.of(LABEL, "mother")).from("a").next(); 135 | 136 | if (supportsGeoshape) { 137 | g.V(b.of(OUT_V, hercules)).as("a").V(b.of(IN_V, nemean)).addE(b.of(LABEL, "battled")) 138 | .property(TIME, b.of(TIME, 1)).property(PLACE, b.of(PLACE, Geoshape.point(38.1f, 23.7f))).from("a") 139 | .next(); 140 | g.V(b.of(OUT_V, hercules)).as("a").V(b.of(IN_V, hydra)).addE(b.of(LABEL, "battled")) 141 | .property(TIME, b.of(TIME, 2)).property(PLACE, b.of(PLACE, Geoshape.point(37.7f, 23.9f))).from("a") 142 | .next(); 143 | g.V(b.of(OUT_V, hercules)).as("a").V(b.of(IN_V, cerberus)).addE(b.of(LABEL, "battled")) 144 | .property(TIME, b.of(TIME, 12)).property(PLACE, b.of(PLACE, Geoshape.point(39f, 22f))).from("a") 145 | .next(); 146 | } else { 147 | g.V(b.of(OUT_V, hercules)).as("a").V(b.of(IN_V, nemean)).addE(b.of(LABEL, "battled")) 148 | .property(TIME, b.of(TIME, 1)).property(PLACE, b.of(PLACE, getGeoFloatArray(38.1f, 23.7f))) 149 | .from("a").next(); 150 | g.V(b.of(OUT_V, hercules)).as("a").V(b.of(IN_V, hydra)).addE(b.of(LABEL, "battled")) 151 | .property(TIME, b.of(TIME, 2)).property(PLACE, b.of(PLACE, getGeoFloatArray(37.7f, 23.9f))) 152 | .from("a").next(); 153 | g.V(b.of(OUT_V, hercules)).as("a").V(b.of(IN_V, cerberus)).addE(b.of(LABEL, "battled")) 154 | .property(TIME, b.of(TIME, 12)).property(PLACE, b.of(PLACE, getGeoFloatArray(39f, 22f))).from("a") 155 | .next(); 156 | } 157 | 158 | g.V(b.of(OUT_V, pluto)).as("a").V(b.of(IN_V, jupiter)).addE(b.of(LABEL, "brother")).from("a").next(); 159 | g.V(b.of(OUT_V, pluto)).as("a").V(b.of(IN_V, neptune)).addE(b.of(LABEL, "brother")).from("a").next(); 160 | g.V(b.of(OUT_V, pluto)).as("a").V(b.of(IN_V, tartarus)).addE(b.of(LABEL, "lives")) 161 | .property(REASON, b.of(REASON, "no fear of death")).from("a").next(); 162 | g.V(b.of(OUT_V, pluto)).as("a").V(b.of(IN_V, cerberus)).addE(b.of(LABEL, "pet")).from("a").next(); 163 | 164 | g.V(b.of(OUT_V, cerberus)).as("a").V(b.of(IN_V, tartarus)).addE(b.of(LABEL, "lives")).from("a").next(); 165 | } 166 | 167 | @Override 168 | public void closeGraph() throws Exception { 169 | LOGGER.info("closing graph"); 170 | try { 171 | if (g != null) { 172 | // this closes the remote, no need to close the empty graph 173 | g.close(); 174 | } 175 | if (cluster != null) { 176 | // the cluster closes all of its clients 177 | cluster.close(); 178 | } 179 | } finally { 180 | g = null; 181 | graph = null; 182 | client = null; 183 | cluster = null; 184 | } 185 | } 186 | 187 | @Override 188 | public void createSchema() { 189 | LOGGER.info("creating schema"); 190 | // get the schema request as a string 191 | final String req = createSchemaRequest(); 192 | // submit the request to the server 193 | final ResultSet resultSet = client.submit(req); 194 | // drain the results completely 195 | Stream futureList = resultSet.stream(); 196 | futureList.map(Result::toString).forEach(LOGGER::info); 197 | } 198 | } 199 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | --------------------------------------------------------------------------------