From f53c60519f11bceae3a8336b0ba25433854a3c38 Mon Sep 17 00:00:00 2001 From: liningrui Date: Tue, 16 Apr 2019 16:50:56 +0800 Subject: [PATCH 1/7] Adapt neighborrank and personalrank API Change-Id: I5f881af79bd514d117e903b9ee823ca87daad82a --- .../api/traverser/NeighborRankAPI.java | 45 ++++++ .../api/traverser/PersonalRankAPI.java | 45 ++++++ .../api/traverser/TraversersAPI.java | 6 + .../api/traverser/structure/Ranks.java | 4 + .../baidu/hugegraph/driver/HugeClient.java | 2 +- .../hugegraph/driver/TraverserManager.java | 9 ++ .../structure/constant/Traverser.java | 2 + .../com/baidu/hugegraph/api/BaseApiTest.java | 3 + .../baidu/hugegraph/api/TraverserApiTest.java | 141 ++++++++++++++++++ 9 files changed, 256 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/baidu/hugegraph/api/traverser/NeighborRankAPI.java create mode 100644 src/main/java/com/baidu/hugegraph/api/traverser/PersonalRankAPI.java create mode 100644 src/main/java/com/baidu/hugegraph/api/traverser/structure/Ranks.java diff --git a/src/main/java/com/baidu/hugegraph/api/traverser/NeighborRankAPI.java b/src/main/java/com/baidu/hugegraph/api/traverser/NeighborRankAPI.java new file mode 100644 index 00000000..61a5448b --- /dev/null +++ b/src/main/java/com/baidu/hugegraph/api/traverser/NeighborRankAPI.java @@ -0,0 +1,45 @@ +/* + * Copyright 2017 HugeGraph Authors + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with this + * work for additional information regarding copyright ownership. The ASF + * licenses this file to You under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +package com.baidu.hugegraph.api.traverser; + +import java.util.List; +import java.util.Map; + +import com.baidu.hugegraph.api.traverser.structure.RankRequest; +import com.baidu.hugegraph.client.RestClient; +import com.baidu.hugegraph.rest.RestResult; + +public class NeighborRankAPI extends TraversersAPI { + + public NeighborRankAPI(RestClient client, String graph) { + super(client, graph); + } + + @Override + protected String type() { + return "neighborrank"; + } + + public List> post(RankRequest request) { + RestResult result = this.client.post(this.path(), request); + // TODO: + return result.readObject(List.class); + } +} diff --git a/src/main/java/com/baidu/hugegraph/api/traverser/PersonalRankAPI.java b/src/main/java/com/baidu/hugegraph/api/traverser/PersonalRankAPI.java new file mode 100644 index 00000000..4d812370 --- /dev/null +++ b/src/main/java/com/baidu/hugegraph/api/traverser/PersonalRankAPI.java @@ -0,0 +1,45 @@ +/* + * Copyright 2017 HugeGraph Authors + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with this + * work for additional information regarding copyright ownership. The ASF + * licenses this file to You under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +package com.baidu.hugegraph.api.traverser; + +import java.util.List; +import java.util.Map; + +import com.baidu.hugegraph.api.traverser.structure.RankRequest; +import com.baidu.hugegraph.client.RestClient; +import com.baidu.hugegraph.rest.RestResult; + +public class NeighborRankAPI extends TraversersAPI { + + public NeighborRankAPI(RestClient client, String graph) { + super(client, graph); + } + + @Override + protected String type() { + return "neighborrank"; + } + + @SuppressWarnings("unchecked") + public List> post(RankRequest request) { + RestResult result = this.client.post(this.path(), request); + return result.readObject(List.class); + } +} diff --git a/src/main/java/com/baidu/hugegraph/api/traverser/TraversersAPI.java b/src/main/java/com/baidu/hugegraph/api/traverser/TraversersAPI.java index 1d963bc9..b6f4cc25 100644 --- a/src/main/java/com/baidu/hugegraph/api/traverser/TraversersAPI.java +++ b/src/main/java/com/baidu/hugegraph/api/traverser/TraversersAPI.java @@ -53,4 +53,10 @@ public static void checkCapacity(long capacity) { public static void checkLimit(long limit) { checkLimit(limit, "Limit"); } + + public static void checkAlpha(double alpha) { + E.checkArgument(alpha > 0 && alpha <= 1.0, + "The alpha of rank request must belong (0, 1], " + + "but got '%s'", alpha); + } } diff --git a/src/main/java/com/baidu/hugegraph/api/traverser/structure/Ranks.java b/src/main/java/com/baidu/hugegraph/api/traverser/structure/Ranks.java new file mode 100644 index 00000000..88e570f6 --- /dev/null +++ b/src/main/java/com/baidu/hugegraph/api/traverser/structure/Ranks.java @@ -0,0 +1,4 @@ +package com.baidu.hugegraph.api.traverser.structure; + +public class Ranks { +} diff --git a/src/main/java/com/baidu/hugegraph/driver/HugeClient.java b/src/main/java/com/baidu/hugegraph/driver/HugeClient.java index f01c6c1e..614f4ac0 100644 --- a/src/main/java/com/baidu/hugegraph/driver/HugeClient.java +++ b/src/main/java/com/baidu/hugegraph/driver/HugeClient.java @@ -118,7 +118,7 @@ private void initManagers(RestClient client, String graph) { private void checkServerApiVersion() { VersionUtil.Version apiVersion = VersionUtil.Version.of( this.version.getApiVersion()); - VersionUtil.check(apiVersion, "0.37", "0.38", + VersionUtil.check(apiVersion, "0.38", "0.39", "hugegraph-api in server"); } diff --git a/src/main/java/com/baidu/hugegraph/driver/TraverserManager.java b/src/main/java/com/baidu/hugegraph/driver/TraverserManager.java index c9bcd90b..a6810ed0 100644 --- a/src/main/java/com/baidu/hugegraph/driver/TraverserManager.java +++ b/src/main/java/com/baidu/hugegraph/driver/TraverserManager.java @@ -20,6 +20,7 @@ package com.baidu.hugegraph.driver; import java.util.List; +import java.util.Map; import com.baidu.hugegraph.api.traverser.CrosspointsAPI; import com.baidu.hugegraph.api.traverser.CustomizedCrosspointsAPI; @@ -27,6 +28,7 @@ import com.baidu.hugegraph.api.traverser.EdgesAPI; import com.baidu.hugegraph.api.traverser.KneighborAPI; import com.baidu.hugegraph.api.traverser.KoutAPI; +import com.baidu.hugegraph.api.traverser.NeighborRankAPI; import com.baidu.hugegraph.api.traverser.PathsAPI; import com.baidu.hugegraph.api.traverser.RaysAPI; import com.baidu.hugegraph.api.traverser.RingsAPI; @@ -36,6 +38,7 @@ import com.baidu.hugegraph.api.traverser.structure.CustomizedCrosspoints; import com.baidu.hugegraph.api.traverser.structure.CustomizedPaths; import com.baidu.hugegraph.api.traverser.structure.PathsRequest; +import com.baidu.hugegraph.api.traverser.structure.RankRequest; import com.baidu.hugegraph.client.RestClient; import com.baidu.hugegraph.structure.constant.Direction; import com.baidu.hugegraph.structure.graph.Edge; @@ -65,6 +68,7 @@ public class TraverserManager { private RaysAPI raysAPI; private CustomizedPathsAPI customizedPathsAPI; private CustomizedCrosspointsAPI customizedCrosspointsAPI; + private NeighborRankAPI neighborRankAPI; private VerticesAPI verticesAPI; private EdgesAPI edgesAPI; @@ -81,6 +85,7 @@ public TraverserManager(RestClient client, GraphManager graphManager) { this.customizedPathsAPI = new CustomizedPathsAPI(client, graph); this.customizedCrosspointsAPI = new CustomizedCrosspointsAPI(client, graph); + this.neighborRankAPI = new NeighborRankAPI(client, graph); this.verticesAPI = new VerticesAPI(client, graph); this.edgesAPI = new EdgesAPI(client, graph); } @@ -209,6 +214,10 @@ public CustomizedCrosspoints customizedCrosspointss( return this.customizedCrosspointsAPI.post(request); } + public List> neighborrank(RankRequest request) { + return this.neighborRankAPI.post(request); + } + public List vertexShards(long splitSize) { return this.verticesAPI.shards(splitSize); } diff --git a/src/main/java/com/baidu/hugegraph/structure/constant/Traverser.java b/src/main/java/com/baidu/hugegraph/structure/constant/Traverser.java index 91fb186b..592c9b0c 100644 --- a/src/main/java/com/baidu/hugegraph/structure/constant/Traverser.java +++ b/src/main/java/com/baidu/hugegraph/structure/constant/Traverser.java @@ -29,4 +29,6 @@ public class Traverser { public static final long DEFAULT_SAMPLE = 100L; public static final double DEFAULT_WEIGHT = 0.0D; public static final long DEFAULT_PAGE_LIMIT = 100_000L; + public static final double DEFAULT_ALPHA = 0.9; + public static final int DEFAULT_MAX_TOP = 100_000; } diff --git a/src/test/java/com/baidu/hugegraph/api/BaseApiTest.java b/src/test/java/com/baidu/hugegraph/api/BaseApiTest.java index 8bca4290..325ea0dd 100644 --- a/src/test/java/com/baidu/hugegraph/api/BaseApiTest.java +++ b/src/test/java/com/baidu/hugegraph/api/BaseApiTest.java @@ -41,6 +41,7 @@ import com.baidu.hugegraph.api.traverser.EdgesAPI; import com.baidu.hugegraph.api.traverser.KneighborAPI; import com.baidu.hugegraph.api.traverser.KoutAPI; +import com.baidu.hugegraph.api.traverser.NeighborRankAPI; import com.baidu.hugegraph.api.traverser.PathsAPI; import com.baidu.hugegraph.api.traverser.RaysAPI; import com.baidu.hugegraph.api.traverser.RingsAPI; @@ -70,6 +71,7 @@ public class BaseApiTest extends BaseClientTest { protected static RaysAPI raysAPI; protected static CustomizedPathsAPI customizedPathsAPI; protected static CustomizedCrosspointsAPI customizedCrosspointsAPI; + protected static NeighborRankAPI neighborRankAPI; protected static VerticesAPI verticesAPI; protected static EdgesAPI edgesAPI; protected static TaskAPI taskAPI; @@ -97,6 +99,7 @@ public static void init() { raysAPI = new RaysAPI(client, GRAPH); customizedPathsAPI = new CustomizedPathsAPI(client, GRAPH); customizedCrosspointsAPI = new CustomizedCrosspointsAPI(client, GRAPH); + neighborRankAPI = new NeighborRankAPI(client, GRAPH); verticesAPI = new VerticesAPI(client, GRAPH); edgesAPI = new EdgesAPI(client, GRAPH); taskAPI = new TaskAPI(client, GRAPH); diff --git a/src/test/java/com/baidu/hugegraph/api/TraverserApiTest.java b/src/test/java/com/baidu/hugegraph/api/TraverserApiTest.java index d1a9a06e..72d00129 100644 --- a/src/test/java/com/baidu/hugegraph/api/TraverserApiTest.java +++ b/src/test/java/com/baidu/hugegraph/api/TraverserApiTest.java @@ -33,6 +33,8 @@ import com.baidu.hugegraph.api.traverser.structure.CustomizedCrosspoints; import com.baidu.hugegraph.api.traverser.structure.CustomizedPaths; import com.baidu.hugegraph.api.traverser.structure.PathsRequest; +import com.baidu.hugegraph.api.traverser.structure.RankRequest; +import com.baidu.hugegraph.driver.GraphManager; import com.baidu.hugegraph.driver.SchemaManager; import com.baidu.hugegraph.exception.ServerException; import com.baidu.hugegraph.structure.constant.Direction; @@ -913,6 +915,71 @@ public void testCustomizedCrosspoints() { Assert.assertTrue(expectedVids.containsAll(vertices)); } + @Test + public void testNeighborRank() { + initNeighborRankGraph(); + + RankRequest.Builder builder = new RankRequest.Builder(); + builder.source("O"); + builder.steps().direction(Direction.OUT).degree(-1).top(10); + builder.steps().direction(Direction.OUT).degree(-1).top(10); + builder.steps().direction(Direction.OUT).degree(-1).top(10); + builder.alpha(0.9).capacity(-1); + RankRequest request = builder.build(); + + List> ranks = neighborRankAPI.post(request); + Assert.assertEquals(4, ranks.size()); + Assert.assertEquals(ImmutableMap.of("O", 1.0D), ranks.get(0)); + + Assert.assertEquals(ImmutableMap.of("B", 0.45075000000000004D, + "A", 0.3D, + "C", 0.3D), + ranks.get(1)); + Assert.assertEquals(ImmutableMap.builder() + .put("G", 0.17550000000000002D) + .put("H", 0.17550000000000002D) + .put("E", 0.135D) + .put("F", 0.135D) + .put("I", 0.135D) + .put("J", 0.135D) + .build(), + ranks.get(2)); + Assert.assertEquals(ImmutableMap.of("M", 0.15795D, + "K", 0.12150000000000001D, + "L", 0.12150000000000001D), + ranks.get(3)); + } + + @Test + public void testNeighborRankWithTop() { + initNeighborRankGraph(); + + RankRequest.Builder builder = new RankRequest.Builder(); + builder.source("O"); + builder.steps().direction(Direction.OUT).degree(-1).top(2); + builder.steps().direction(Direction.OUT).degree(-1).top(3); + builder.steps().direction(Direction.OUT).degree(-1).top(2); + builder.alpha(0.9).capacity(-1); + RankRequest request = builder.build(); + + List> ranks = neighborRankAPI.post(request); + Assert.assertEquals(4, ranks.size()); + Assert.assertEquals(ImmutableMap.of("O", 1.0D), ranks.get(0)); + + Assert.assertEquals(ImmutableMap.of("B", 0.45075000000000004D, + "A", 0.3D), + ranks.get(1)); + Assert.assertEquals(ImmutableMap.builder() + .put("G", 0.17550000000000002D) + .put("H", 0.17550000000000002D) + .put("E", 0.135D) + .build(), + ranks.get(2)); + Assert.assertEquals(ImmutableMap.of("M", 0.15795D, + "K", 0.12150000000000001D), + ranks.get(3)); + } + @Test public void testVertices() { Object markoId = getVertexId("person", "name", "marko"); @@ -1102,4 +1169,78 @@ private static void removeEdgesWithWeights() { }); elTaskIds.forEach(BaseApiTest::waitUntilTaskCompleted); } + + private static void initNeighborRankGraph() { + GraphManager graph = graph(); + SchemaManager schema = schema(); + + schema.vertexLabel("m_person") + .properties("name") + .useCustomizeStringId() + .ifNotExist() + .create(); + + schema.vertexLabel("movie") + .properties("name") + .useCustomizeStringId() + .ifNotExist() + .create(); + + schema.edgeLabel("follow") + .sourceLabel("m_person") + .targetLabel("m_person") + .ifNotExist() + .create(); + + schema.edgeLabel("like") + .sourceLabel("m_person") + .targetLabel("movie") + .ifNotExist() + .create(); + + schema.edgeLabel("directedby") + .sourceLabel("movie") + .targetLabel("m_person") + .ifNotExist() + .create(); + + Vertex O = graph.addVertex(T.label, "m_person", T.id, "O", "name", "O"); + + Vertex A = graph.addVertex(T.label, "m_person", T.id, "A", "name", "A"); + Vertex B = graph.addVertex(T.label, "m_person", T.id, "B", "name", "B"); + Vertex C = graph.addVertex(T.label, "m_person", T.id, "C", "name", "C"); + Vertex D = graph.addVertex(T.label, "m_person", T.id, "D", "name", "D"); + + Vertex E = graph.addVertex(T.label, "movie", T.id, "E", "name", "E"); + Vertex F = graph.addVertex(T.label, "movie", T.id, "F", "name", "F"); + Vertex G = graph.addVertex(T.label, "movie", T.id, "G", "name", "G"); + Vertex H = graph.addVertex(T.label, "movie", T.id, "H", "name", "H"); + Vertex I = graph.addVertex(T.label, "movie", T.id, "I", "name", "I"); + Vertex J = graph.addVertex(T.label, "movie", T.id, "J", "name", "J"); + + Vertex K = graph.addVertex(T.label, "m_person", T.id, "K", "name", "K"); + Vertex L = graph.addVertex(T.label, "m_person", T.id, "L", "name", "L"); + Vertex M = graph.addVertex(T.label, "m_person", T.id, "M", "name", "M"); + + O.addEdge("follow", A); + O.addEdge("follow", B); + O.addEdge("follow", C); + D.addEdge("follow", O); + + A.addEdge("follow", B); + A.addEdge("like", E); + A.addEdge("like", F); + + B.addEdge("like", G); + B.addEdge("like", H); + + C.addEdge("like", I); + C.addEdge("like", J); + + E.addEdge("directedby", K); + F.addEdge("directedby", B); + F.addEdge("directedby", L); + + G.addEdge("directedby", M); + } } From 7ce23a359375ba61db0c84ed15f097747545fb6b Mon Sep 17 00:00:00 2001 From: liningrui Date: Tue, 16 Apr 2019 21:55:04 +0800 Subject: [PATCH 2/7] Add personalrank API Change-Id: I762a167a28628d775f8ddd5dd43c9e23efa3f002 --- pom.xml | 6 +- .../api/traverser/NeighborRankAPI.java | 162 +++++++++++++++++- .../api/traverser/PersonalRankAPI.java | 100 ++++++++++- .../api/traverser/structure/Ranks.java | 24 ++- .../hugegraph/driver/TraverserManager.java | 12 +- .../hugegraph/version/ClientVersion.java | 2 +- .../com/baidu/hugegraph/api/BaseApiTest.java | 3 + .../baidu/hugegraph/api/TraverserApiTest.java | 104 +++++++++-- 8 files changed, 377 insertions(+), 36 deletions(-) diff --git a/pom.xml b/pom.xml index fd14087e..98743c30 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.baidu.hugegraph hugegraph-client - 1.6.12 + 1.7.0 jar hugegraph-client @@ -53,7 +53,7 @@ UTF-8 1.8 1.8 - 1.5.9 + 1.6.0 2.22 2.8.47 @@ -113,7 +113,7 @@ - 1.6.12.0 + 1.7.0.0 diff --git a/src/main/java/com/baidu/hugegraph/api/traverser/NeighborRankAPI.java b/src/main/java/com/baidu/hugegraph/api/traverser/NeighborRankAPI.java index 61a5448b..7272fbe0 100644 --- a/src/main/java/com/baidu/hugegraph/api/traverser/NeighborRankAPI.java +++ b/src/main/java/com/baidu/hugegraph/api/traverser/NeighborRankAPI.java @@ -19,12 +19,18 @@ package com.baidu.hugegraph.api.traverser; +import java.util.ArrayList; +import java.util.Arrays; import java.util.List; -import java.util.Map; -import com.baidu.hugegraph.api.traverser.structure.RankRequest; +import com.baidu.hugegraph.api.graph.GraphAPI; +import com.baidu.hugegraph.api.traverser.structure.Ranks; import com.baidu.hugegraph.client.RestClient; import com.baidu.hugegraph.rest.RestResult; +import com.baidu.hugegraph.structure.constant.Direction; +import com.baidu.hugegraph.structure.constant.Traverser; +import com.baidu.hugegraph.util.E; +import com.fasterxml.jackson.annotation.JsonProperty; public class NeighborRankAPI extends TraversersAPI { @@ -37,9 +43,155 @@ protected String type() { return "neighborrank"; } - public List> post(RankRequest request) { + public List post(RankRequest request) { RestResult result = this.client.post(this.path(), request); - // TODO: - return result.readObject(List.class); + return result.readList("ranks", Ranks.class); + } + + public static class RankRequest { + + @JsonProperty("source") + private String source; + @JsonProperty("steps") + private List steps; + @JsonProperty("alpha") + private double alpha; + @JsonProperty("capacity") + private long capacity; + + private RankRequest() { + this.source = null; + this.steps = new ArrayList<>(); + this.alpha = Traverser.DEFAULT_ALPHA; + this.capacity = Traverser.DEFAULT_CAPACITY; + } + + @Override + public String toString() { + return String.format("RankRequest{source=%s,steps=%s,alpha=%s," + + "capacity=%s}", this.source, this.steps, + this.alpha, this.capacity); + } + + public static class Builder { + + private RankRequest request; + private List stepBuilders; + + public Builder() { + this.request = new RankRequest(); + this.stepBuilders = new ArrayList<>(); + } + + public Builder source(Object source) { + this.request.source = GraphAPI.formatVertexId(source); + return this; + } + + public Step.Builder steps() { + Step.Builder builder = new Step.Builder(); + this.stepBuilders.add(builder); + return builder; + } + + public Builder alpha(double alpha) { + TraversersAPI.checkAlpha(alpha); + this.request.alpha = alpha; + return this; + } + + public Builder capacity(long capacity) { + TraversersAPI.checkCapacity(capacity); + this.request.capacity = capacity; + return this; + } + + public RankRequest build() { + for (Step.Builder builder : this.stepBuilders) { + this.request.steps.add(builder.build()); + } + E.checkArgument(this.request.source != null, + "Source vertex can't be null"); + E.checkArgument(this.request.steps != null && + !this.request.steps.isEmpty(), + "Steps can't be null or empty"); + TraversersAPI.checkCapacity(this.request.capacity); + TraversersAPI.checkAlpha(this.request.alpha); + return this.request; + } + } + + public static class Step { + + @JsonProperty("direction") + private String direction; + @JsonProperty("labels") + private List labels; + @JsonProperty("degree") + private long degree; + @JsonProperty("top") + private int top; + + private Step() { + this.direction = null; + this.labels = new ArrayList<>(); + this.degree = Traverser.DEFAULT_DEGREE; + this.top = (int) Traverser.DEFAULT_PATHS_LIMIT; + } + + @Override + public String toString() { + return String.format("Step{direction=%s,labels=%s,degree=%s," + + "top=%s}", this.direction, this.labels, + this.degree, this.top); + } + + public static class Builder { + + private Step step; + + private Builder() { + this.step = new Step(); + } + + public Step.Builder direction(Direction direction) { + this.step.direction = direction.toString(); + return this; + } + + public Step.Builder labels(List labels) { + this.step.labels.addAll(labels); + return this; + } + + public Step.Builder labels(String... labels) { + this.step.labels.addAll(Arrays.asList(labels)); + return this; + } + + public Step.Builder degree(long degree) { + TraversersAPI.checkDegree(degree); + this.step.degree = degree; + return this; + } + + public Step.Builder top(int top) { + E.checkArgument(top > 0 && top <= Traverser.DEFAULT_MAX_TOP, + "The top of each layer cannot exceed %s", + Traverser.DEFAULT_MAX_TOP); + this.step.top = top; + return this; + } + + private Step build() { + TraversersAPI.checkDegree(this.step.degree); + E.checkArgument(this.step.top > 0 && + this.step.top <= Traverser.DEFAULT_MAX_TOP, + "The top of each layer cannot exceed %s", + Traverser.DEFAULT_MAX_TOP); + return this.step; + } + } + } } } diff --git a/src/main/java/com/baidu/hugegraph/api/traverser/PersonalRankAPI.java b/src/main/java/com/baidu/hugegraph/api/traverser/PersonalRankAPI.java index 4d812370..48567c8b 100644 --- a/src/main/java/com/baidu/hugegraph/api/traverser/PersonalRankAPI.java +++ b/src/main/java/com/baidu/hugegraph/api/traverser/PersonalRankAPI.java @@ -19,27 +19,115 @@ package com.baidu.hugegraph.api.traverser; +import java.util.ArrayList; import java.util.List; import java.util.Map; -import com.baidu.hugegraph.api.traverser.structure.RankRequest; +import com.baidu.hugegraph.api.graph.GraphAPI; import com.baidu.hugegraph.client.RestClient; import com.baidu.hugegraph.rest.RestResult; +import com.baidu.hugegraph.structure.constant.Traverser; +import com.baidu.hugegraph.util.E; +import com.fasterxml.jackson.annotation.JsonProperty; -public class NeighborRankAPI extends TraversersAPI { +public class PersonalRankAPI extends TraversersAPI { - public NeighborRankAPI(RestClient client, String graph) { + public PersonalRankAPI(RestClient client, String graph) { super(client, graph); } @Override protected String type() { - return "neighborrank"; + return "personalrank"; } @SuppressWarnings("unchecked") - public List> post(RankRequest request) { + public Map post(RankRequest request) { RestResult result = this.client.post(this.path(), request); - return result.readObject(List.class); + return result.readObject(Map.class); + } + + public static class RankRequest { + + @JsonProperty("source") + private String source; + @JsonProperty("label") + private String label; + @JsonProperty("alpha") + private double alpha; + @JsonProperty("degree") + public long degree = Traverser.DEFAULT_DEGREE; + @JsonProperty("max_depth") + private int maxDepth; + @JsonProperty("sorted") + private boolean sorted = true; + + @Override + public String toString() { + return String.format("RankRequest{source=%s,label=%s," + + "alpha=%s,degree=%s,maxDepth=%s,sorted=%s}", + this.source, this.label, this.alpha, + this.degree, this.maxDepth, this.sorted); + } + + public static class Builder { + + private RankRequest request; + + public Builder() { + this.request = new RankRequest(); + } + + public Builder source(Object source) { + this.request.source = GraphAPI.formatVertexId(source); + return this; + } + + public Builder label(String label) { + E.checkArgument(label != null, "The label of rank request " + + "for personal rank can't be null"); + this.request.label = label; + return this; + } + + public Builder alpha(double alpha) { + TraversersAPI.checkAlpha(alpha); + this.request.alpha = alpha; + return this; + } + + public Builder degree(long degree) { + TraversersAPI.checkDegree(degree); + this.request.degree = degree; + return this; + } + + public Builder maxDepth(int maxDepth) { + TraversersAPI.checkPositive(maxDepth, + "max depth of rank request " + + "for personal rank"); + this.request.maxDepth = maxDepth; + return this; + } + + public Builder sorted(boolean sorted) { + this.request.sorted = sorted; + return this; + } + + public RankRequest build() { + E.checkArgument(this.request.source != null, + "Source vertex can't be null"); + E.checkArgument(this.request.label != null, + "The label of rank request " + + "for personal rank can't be null"); + TraversersAPI.checkAlpha(this.request.alpha); + TraversersAPI.checkDegree(this.request.degree); + TraversersAPI.checkPositive(this.request.maxDepth, + "max depth of rank request " + + "for personal rank"); + return this.request; + } + } } } diff --git a/src/main/java/com/baidu/hugegraph/api/traverser/structure/Ranks.java b/src/main/java/com/baidu/hugegraph/api/traverser/structure/Ranks.java index 88e570f6..0d834005 100644 --- a/src/main/java/com/baidu/hugegraph/api/traverser/structure/Ranks.java +++ b/src/main/java/com/baidu/hugegraph/api/traverser/structure/Ranks.java @@ -1,4 +1,26 @@ +/* + * Copyright 2017 HugeGraph Authors + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with this + * work for additional information regarding copyright ownership. The ASF + * licenses this file to You under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + package com.baidu.hugegraph.api.traverser.structure; -public class Ranks { +import java.util.HashMap; + +public class Ranks extends HashMap { + } diff --git a/src/main/java/com/baidu/hugegraph/driver/TraverserManager.java b/src/main/java/com/baidu/hugegraph/driver/TraverserManager.java index a6810ed0..7e9f70d6 100644 --- a/src/main/java/com/baidu/hugegraph/driver/TraverserManager.java +++ b/src/main/java/com/baidu/hugegraph/driver/TraverserManager.java @@ -30,6 +30,7 @@ import com.baidu.hugegraph.api.traverser.KoutAPI; import com.baidu.hugegraph.api.traverser.NeighborRankAPI; import com.baidu.hugegraph.api.traverser.PathsAPI; +import com.baidu.hugegraph.api.traverser.PersonalRankAPI; import com.baidu.hugegraph.api.traverser.RaysAPI; import com.baidu.hugegraph.api.traverser.RingsAPI; import com.baidu.hugegraph.api.traverser.ShortestPathAPI; @@ -38,7 +39,6 @@ import com.baidu.hugegraph.api.traverser.structure.CustomizedCrosspoints; import com.baidu.hugegraph.api.traverser.structure.CustomizedPaths; import com.baidu.hugegraph.api.traverser.structure.PathsRequest; -import com.baidu.hugegraph.api.traverser.structure.RankRequest; import com.baidu.hugegraph.client.RestClient; import com.baidu.hugegraph.structure.constant.Direction; import com.baidu.hugegraph.structure.graph.Edge; @@ -69,6 +69,7 @@ public class TraverserManager { private CustomizedPathsAPI customizedPathsAPI; private CustomizedCrosspointsAPI customizedCrosspointsAPI; private NeighborRankAPI neighborRankAPI; + private PersonalRankAPI personalRankAPI; private VerticesAPI verticesAPI; private EdgesAPI edgesAPI; @@ -86,6 +87,7 @@ public TraverserManager(RestClient client, GraphManager graphManager) { this.customizedCrosspointsAPI = new CustomizedCrosspointsAPI(client, graph); this.neighborRankAPI = new NeighborRankAPI(client, graph); + this.personalRankAPI = new PersonalRankAPI(client, graph); this.verticesAPI = new VerticesAPI(client, graph); this.edgesAPI = new EdgesAPI(client, graph); } @@ -214,10 +216,16 @@ public CustomizedCrosspoints customizedCrosspointss( return this.customizedCrosspointsAPI.post(request); } - public List> neighborrank(RankRequest request) { + public List> neighborRank( + NeighborRankAPI.RankRequest request) { return this.neighborRankAPI.post(request); } + public Map personalRank( + PersonalRankAPI.RankRequest request) { + return this.personalRankAPI.post(request); + } + public List vertexShards(long splitSize) { return this.verticesAPI.shards(splitSize); } diff --git a/src/main/java/com/baidu/hugegraph/version/ClientVersion.java b/src/main/java/com/baidu/hugegraph/version/ClientVersion.java index 41ced547..e8769958 100644 --- a/src/main/java/com/baidu/hugegraph/version/ClientVersion.java +++ b/src/main/java/com/baidu/hugegraph/version/ClientVersion.java @@ -35,7 +35,7 @@ public class ClientVersion { public static final void check() { // Check version of hugegraph-common - VersionUtil.check(CommonVersion.VERSION, "1.5", "1.6", + VersionUtil.check(CommonVersion.VERSION, "1.6", "1.7", CommonVersion.NAME); } } diff --git a/src/test/java/com/baidu/hugegraph/api/BaseApiTest.java b/src/test/java/com/baidu/hugegraph/api/BaseApiTest.java index 325ea0dd..9aeb7bf1 100644 --- a/src/test/java/com/baidu/hugegraph/api/BaseApiTest.java +++ b/src/test/java/com/baidu/hugegraph/api/BaseApiTest.java @@ -43,6 +43,7 @@ import com.baidu.hugegraph.api.traverser.KoutAPI; import com.baidu.hugegraph.api.traverser.NeighborRankAPI; import com.baidu.hugegraph.api.traverser.PathsAPI; +import com.baidu.hugegraph.api.traverser.PersonalRankAPI; import com.baidu.hugegraph.api.traverser.RaysAPI; import com.baidu.hugegraph.api.traverser.RingsAPI; import com.baidu.hugegraph.api.traverser.ShortestPathAPI; @@ -72,6 +73,7 @@ public class BaseApiTest extends BaseClientTest { protected static CustomizedPathsAPI customizedPathsAPI; protected static CustomizedCrosspointsAPI customizedCrosspointsAPI; protected static NeighborRankAPI neighborRankAPI; + protected static PersonalRankAPI personalRankAPI; protected static VerticesAPI verticesAPI; protected static EdgesAPI edgesAPI; protected static TaskAPI taskAPI; @@ -100,6 +102,7 @@ public static void init() { customizedPathsAPI = new CustomizedPathsAPI(client, GRAPH); customizedCrosspointsAPI = new CustomizedCrosspointsAPI(client, GRAPH); neighborRankAPI = new NeighborRankAPI(client, GRAPH); + personalRankAPI = new PersonalRankAPI(client, GRAPH); verticesAPI = new VerticesAPI(client, GRAPH); edgesAPI = new EdgesAPI(client, GRAPH); taskAPI = new TaskAPI(client, GRAPH); diff --git a/src/test/java/com/baidu/hugegraph/api/TraverserApiTest.java b/src/test/java/com/baidu/hugegraph/api/TraverserApiTest.java index 72d00129..064ab5da 100644 --- a/src/test/java/com/baidu/hugegraph/api/TraverserApiTest.java +++ b/src/test/java/com/baidu/hugegraph/api/TraverserApiTest.java @@ -29,11 +29,13 @@ import org.junit.BeforeClass; import org.junit.Test; +import com.baidu.hugegraph.api.traverser.NeighborRankAPI; +import com.baidu.hugegraph.api.traverser.PersonalRankAPI; import com.baidu.hugegraph.api.traverser.structure.CrosspointsRequest; import com.baidu.hugegraph.api.traverser.structure.CustomizedCrosspoints; import com.baidu.hugegraph.api.traverser.structure.CustomizedPaths; import com.baidu.hugegraph.api.traverser.structure.PathsRequest; -import com.baidu.hugegraph.api.traverser.structure.RankRequest; +import com.baidu.hugegraph.api.traverser.structure.Ranks; import com.baidu.hugegraph.driver.GraphManager; import com.baidu.hugegraph.driver.SchemaManager; import com.baidu.hugegraph.exception.ServerException; @@ -919,15 +921,16 @@ public void testCustomizedCrosspoints() { public void testNeighborRank() { initNeighborRankGraph(); - RankRequest.Builder builder = new RankRequest.Builder(); + NeighborRankAPI.RankRequest.Builder builder; + builder = new NeighborRankAPI.RankRequest.Builder(); builder.source("O"); builder.steps().direction(Direction.OUT).degree(-1).top(10); builder.steps().direction(Direction.OUT).degree(-1).top(10); builder.steps().direction(Direction.OUT).degree(-1).top(10); builder.alpha(0.9).capacity(-1); - RankRequest request = builder.build(); + NeighborRankAPI.RankRequest request = builder.build(); - List> ranks = neighborRankAPI.post(request); + List ranks = neighborRankAPI.post(request); Assert.assertEquals(4, ranks.size()); Assert.assertEquals(ImmutableMap.of("O", 1.0D), ranks.get(0)); @@ -954,32 +957,52 @@ public void testNeighborRank() { public void testNeighborRankWithTop() { initNeighborRankGraph(); - RankRequest.Builder builder = new RankRequest.Builder(); + NeighborRankAPI.RankRequest.Builder builder; + builder = new NeighborRankAPI.RankRequest.Builder(); builder.source("O"); builder.steps().direction(Direction.OUT).degree(-1).top(2); builder.steps().direction(Direction.OUT).degree(-1).top(3); builder.steps().direction(Direction.OUT).degree(-1).top(2); builder.alpha(0.9).capacity(-1); - RankRequest request = builder.build(); + NeighborRankAPI.RankRequest request = builder.build(); - List> ranks = neighborRankAPI.post(request); + List ranks = neighborRankAPI.post(request); Assert.assertEquals(4, ranks.size()); Assert.assertEquals(ImmutableMap.of("O", 1.0D), ranks.get(0)); Assert.assertEquals(ImmutableMap.of("B", 0.45075000000000004D, "A", 0.3D), ranks.get(1)); - Assert.assertEquals(ImmutableMap.builder() - .put("G", 0.17550000000000002D) - .put("H", 0.17550000000000002D) - .put("E", 0.135D) - .build(), + Assert.assertEquals(ImmutableMap.of("G", 0.17550000000000002D, + "H", 0.17550000000000002D, + "E", 0.135D), ranks.get(2)); Assert.assertEquals(ImmutableMap.of("M", 0.15795D, - "K", 0.12150000000000001D), + "K", 0.12150000000000001D), ranks.get(3)); } + @Test + public void testPersonalRank() { + initPersonalRankGraph(); + + PersonalRankAPI.RankRequest.Builder builder; + builder = new PersonalRankAPI.RankRequest.Builder(); + builder.source("A").label("like").alpha(0.9).maxDepth(50).build(); + PersonalRankAPI.RankRequest request = builder.build(); + + Map ranks = personalRankAPI.post(request); + Assert.assertEquals(ImmutableMap.builder() + .put("A", 0.22378692172243492D) + .put("B", 0.2065750574989044D) + .put("c", 0.18972188606657317) + .put("a", 0.1460239032907022) + .put("C", 0.09839507219265439) + .put("d", 0.08959757100230095) + .put("b", 0.04589958822642998) + .build(), ranks); + } + @Test public void testVertices() { Object markoId = getVertexId("person", "name", "marko"); @@ -1198,7 +1221,7 @@ private static void initNeighborRankGraph() { .ifNotExist() .create(); - schema.edgeLabel("directedby") + schema.edgeLabel("directedBy") .sourceLabel("movie") .targetLabel("m_person") .ifNotExist() @@ -1237,10 +1260,55 @@ private static void initNeighborRankGraph() { C.addEdge("like", I); C.addEdge("like", J); - E.addEdge("directedby", K); - F.addEdge("directedby", B); - F.addEdge("directedby", L); + E.addEdge("directedBy", K); + F.addEdge("directedBy", B); + F.addEdge("directedBy", L); + + G.addEdge("directedBy", M); + } + + private static void initPersonalRankGraph() { + GraphManager graph = graph(); + SchemaManager schema = schema(); + + schema.propertyKey("name").asText().ifNotExist().create(); + + schema.vertexLabel("person") + .properties("name") + .useCustomizeStringId() + .ifNotExist() + .create(); + + schema.vertexLabel("movie") + .properties("name") + .useCustomizeStringId() + .ifNotExist() + .create(); + + schema.edgeLabel("like") + .sourceLabel("person") + .targetLabel("movie") + .ifNotExist() + .create(); + + Vertex A = graph.addVertex(T.label, "person", T.id, "A", "name", "A"); + Vertex B = graph.addVertex(T.label, "person", T.id, "B", "name", "B"); + Vertex C = graph.addVertex(T.label, "person", T.id, "C", "name", "C"); + + Vertex a = graph.addVertex(T.label, "movie", T.id, "a", "name", "a"); + Vertex b = graph.addVertex(T.label, "movie", T.id, "b", "name", "b"); + Vertex c = graph.addVertex(T.label, "movie", T.id, "c", "name", "c"); + Vertex d = graph.addVertex(T.label, "movie", T.id, "d", "name", "d"); + + A.addEdge("like", a); + A.addEdge("like", c); + + B.addEdge("like", a); + B.addEdge("like", b); + B.addEdge("like", c); + B.addEdge("like", d); - G.addEdge("directedby", M); + C.addEdge("like", c); + C.addEdge("like", d); } } From d2b1a78156a194d867b1fca81ed93a6ca8e6f4d6 Mon Sep 17 00:00:00 2001 From: liningrui Date: Wed, 17 Apr 2019 22:09:02 +0800 Subject: [PATCH 3/7] Add some tests Change-Id: If4ab77881e3beab38f755e63e14570c078ded9ab --- .../api/traverser/NeighborRankAPI.java | 20 +- .../api/traverser/PersonalRankAPI.java | 54 +- .../api/traverser/structure/Ranks.java | 5 +- .../hugegraph/driver/TraverserManager.java | 19 +- .../structure/constant/Traverser.java | 1 + .../com/baidu/hugegraph/api/ApiTestSuite.java | 7 +- .../hugegraph/api/CustomizedPathsApiTest.java | 371 ++++++++++++ .../hugegraph/api/NeighborRankApiTest.java | 348 +++++++++++ .../hugegraph/api/PersonalRankApiTest.java | 255 +++++++++ .../baidu/hugegraph/api/TraverserApiTest.java | 538 +----------------- 10 files changed, 1043 insertions(+), 575 deletions(-) create mode 100644 src/test/java/com/baidu/hugegraph/api/CustomizedPathsApiTest.java create mode 100644 src/test/java/com/baidu/hugegraph/api/NeighborRankApiTest.java create mode 100644 src/test/java/com/baidu/hugegraph/api/PersonalRankApiTest.java diff --git a/src/main/java/com/baidu/hugegraph/api/traverser/NeighborRankAPI.java b/src/main/java/com/baidu/hugegraph/api/traverser/NeighborRankAPI.java index 7272fbe0..4095ca45 100644 --- a/src/main/java/com/baidu/hugegraph/api/traverser/NeighborRankAPI.java +++ b/src/main/java/com/baidu/hugegraph/api/traverser/NeighborRankAPI.java @@ -43,12 +43,12 @@ protected String type() { return "neighborrank"; } - public List post(RankRequest request) { + public List post(Request request) { RestResult result = this.client.post(this.path(), request); return result.readList("ranks", Ranks.class); } - public static class RankRequest { + public static class Request { @JsonProperty("source") private String source; @@ -59,27 +59,31 @@ public static class RankRequest { @JsonProperty("capacity") private long capacity; - private RankRequest() { + private Request() { this.source = null; this.steps = new ArrayList<>(); this.alpha = Traverser.DEFAULT_ALPHA; this.capacity = Traverser.DEFAULT_CAPACITY; } + public static Builder builder() { + return new Builder(); + } + @Override public String toString() { - return String.format("RankRequest{source=%s,steps=%s,alpha=%s," + + return String.format("Request{source=%s,steps=%s,alpha=%s," + "capacity=%s}", this.source, this.steps, this.alpha, this.capacity); } public static class Builder { - private RankRequest request; + private Request request; private List stepBuilders; - public Builder() { - this.request = new RankRequest(); + private Builder() { + this.request = new Request(); this.stepBuilders = new ArrayList<>(); } @@ -106,7 +110,7 @@ public Builder capacity(long capacity) { return this; } - public RankRequest build() { + public Request build() { for (Step.Builder builder : this.stepBuilders) { this.request.steps.add(builder.build()); } diff --git a/src/main/java/com/baidu/hugegraph/api/traverser/PersonalRankAPI.java b/src/main/java/com/baidu/hugegraph/api/traverser/PersonalRankAPI.java index 48567c8b..3355f0f0 100644 --- a/src/main/java/com/baidu/hugegraph/api/traverser/PersonalRankAPI.java +++ b/src/main/java/com/baidu/hugegraph/api/traverser/PersonalRankAPI.java @@ -19,11 +19,8 @@ package com.baidu.hugegraph.api.traverser; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - import com.baidu.hugegraph.api.graph.GraphAPI; +import com.baidu.hugegraph.api.traverser.structure.Ranks; import com.baidu.hugegraph.client.RestClient; import com.baidu.hugegraph.rest.RestResult; import com.baidu.hugegraph.structure.constant.Traverser; @@ -41,13 +38,12 @@ protected String type() { return "personalrank"; } - @SuppressWarnings("unchecked") - public Map post(RankRequest request) { + public Ranks post(Request request) { RestResult result = this.client.post(this.path(), request); - return result.readObject(Map.class); + return result.readObject(Ranks.class); } - public static class RankRequest { + public static class Request { @JsonProperty("source") private String source; @@ -57,25 +53,41 @@ public static class RankRequest { private double alpha; @JsonProperty("degree") public long degree = Traverser.DEFAULT_DEGREE; + @JsonProperty("limit") + private long limit = Traverser.DEFAULT_LIMIT; @JsonProperty("max_depth") private int maxDepth; + @JsonProperty("with_label") + private WithLabel withLabel = WithLabel.BOTH_LABEL; @JsonProperty("sorted") private boolean sorted = true; + public static Builder builder() { + return new Builder(); + } + @Override public String toString() { - return String.format("RankRequest{source=%s,label=%s," + - "alpha=%s,degree=%s,maxDepth=%s,sorted=%s}", + return String.format("Request{source=%s,label=%s,alpha=%s," + + "degree=%s,limit=%s,maxDepth=%s," + + "withLabel=%s,sorted=%s}", this.source, this.label, this.alpha, - this.degree, this.maxDepth, this.sorted); + this.degree, this.limit, this.maxDepth, + this.withLabel, this.sorted); + } + + public enum WithLabel { + SAME_LABEL, + OTHER_LABEL, + BOTH_LABEL } public static class Builder { - private RankRequest request; + private Request request; - public Builder() { - this.request = new RankRequest(); + private Builder() { + this.request = new Request(); } public Builder source(Object source) { @@ -102,6 +114,12 @@ public Builder degree(long degree) { return this; } + public Builder limit(long limit) { + TraversersAPI.checkLimit(limit); + this.request.limit = limit; + return this; + } + public Builder maxDepth(int maxDepth) { TraversersAPI.checkPositive(maxDepth, "max depth of rank request " + @@ -110,12 +128,17 @@ public Builder maxDepth(int maxDepth) { return this; } + public Builder withLabel(WithLabel withLabel) { + this.request.withLabel = withLabel; + return this; + } + public Builder sorted(boolean sorted) { this.request.sorted = sorted; return this; } - public RankRequest build() { + public Request build() { E.checkArgument(this.request.source != null, "Source vertex can't be null"); E.checkArgument(this.request.label != null, @@ -123,6 +146,7 @@ public RankRequest build() { "for personal rank can't be null"); TraversersAPI.checkAlpha(this.request.alpha); TraversersAPI.checkDegree(this.request.degree); + TraversersAPI.checkLimit(this.request.limit); TraversersAPI.checkPositive(this.request.maxDepth, "max depth of rank request " + "for personal rank"); diff --git a/src/main/java/com/baidu/hugegraph/api/traverser/structure/Ranks.java b/src/main/java/com/baidu/hugegraph/api/traverser/structure/Ranks.java index 0d834005..8be0a341 100644 --- a/src/main/java/com/baidu/hugegraph/api/traverser/structure/Ranks.java +++ b/src/main/java/com/baidu/hugegraph/api/traverser/structure/Ranks.java @@ -19,8 +19,7 @@ package com.baidu.hugegraph.api.traverser.structure; -import java.util.HashMap; - -public class Ranks extends HashMap { +import java.util.LinkedHashMap; +public class Ranks extends LinkedHashMap { } diff --git a/src/main/java/com/baidu/hugegraph/driver/TraverserManager.java b/src/main/java/com/baidu/hugegraph/driver/TraverserManager.java index 7e9f70d6..995f8619 100644 --- a/src/main/java/com/baidu/hugegraph/driver/TraverserManager.java +++ b/src/main/java/com/baidu/hugegraph/driver/TraverserManager.java @@ -19,8 +19,12 @@ package com.baidu.hugegraph.driver; +import static com.baidu.hugegraph.structure.constant.Traverser.DEFAULT_CAPACITY; +import static com.baidu.hugegraph.structure.constant.Traverser.DEFAULT_DEGREE; +import static com.baidu.hugegraph.structure.constant.Traverser.DEFAULT_ELEMENTS_LIMIT; +import static com.baidu.hugegraph.structure.constant.Traverser.DEFAULT_PAGE_LIMIT; + import java.util.List; -import java.util.Map; import com.baidu.hugegraph.api.traverser.CrosspointsAPI; import com.baidu.hugegraph.api.traverser.CustomizedCrosspointsAPI; @@ -39,6 +43,7 @@ import com.baidu.hugegraph.api.traverser.structure.CustomizedCrosspoints; import com.baidu.hugegraph.api.traverser.structure.CustomizedPaths; import com.baidu.hugegraph.api.traverser.structure.PathsRequest; +import com.baidu.hugegraph.api.traverser.structure.Ranks; import com.baidu.hugegraph.client.RestClient; import com.baidu.hugegraph.structure.constant.Direction; import com.baidu.hugegraph.structure.graph.Edge; @@ -49,12 +54,6 @@ import com.baidu.hugegraph.structure.graph.Vertices; import com.baidu.hugegraph.util.E; -import static com.baidu.hugegraph.structure.constant.Traverser.DEFAULT_PAGE_LIMIT; - -import static com.baidu.hugegraph.structure.constant.Traverser.DEFAULT_CAPACITY; -import static com.baidu.hugegraph.structure.constant.Traverser.DEFAULT_DEGREE; -import static com.baidu.hugegraph.structure.constant.Traverser.DEFAULT_ELEMENTS_LIMIT; - public class TraverserManager { private final GraphManager graphManager; @@ -216,13 +215,11 @@ public CustomizedCrosspoints customizedCrosspointss( return this.customizedCrosspointsAPI.post(request); } - public List> neighborRank( - NeighborRankAPI.RankRequest request) { + public List neighborRank(NeighborRankAPI.Request request) { return this.neighborRankAPI.post(request); } - public Map personalRank( - PersonalRankAPI.RankRequest request) { + public Ranks personalRank(PersonalRankAPI.Request request) { return this.personalRankAPI.post(request); } diff --git a/src/main/java/com/baidu/hugegraph/structure/constant/Traverser.java b/src/main/java/com/baidu/hugegraph/structure/constant/Traverser.java index 592c9b0c..15b3bc06 100644 --- a/src/main/java/com/baidu/hugegraph/structure/constant/Traverser.java +++ b/src/main/java/com/baidu/hugegraph/structure/constant/Traverser.java @@ -22,6 +22,7 @@ public class Traverser { public static final long DEFAULT_CAPACITY = 10_000_000L; + public static final long DEFAULT_LIMIT = 100L; public static final long DEFAULT_ELEMENTS_LIMIT = 10_000_000L; public static final long DEFAULT_DEGREE = 10_000L; public static final long DEFAULT_CROSSPOINT_LIMIT = 10_000L; diff --git a/src/test/java/com/baidu/hugegraph/api/ApiTestSuite.java b/src/test/java/com/baidu/hugegraph/api/ApiTestSuite.java index aa845a75..2016184d 100644 --- a/src/test/java/com/baidu/hugegraph/api/ApiTestSuite.java +++ b/src/test/java/com/baidu/hugegraph/api/ApiTestSuite.java @@ -32,10 +32,13 @@ EdgeApiTest.class, GremlinApiTest.class, VariablesApiTest.class, - TraverserApiTest.class, TaskApiTest.class, JobApiTest.class, - RestoreApiTest.class + RestoreApiTest.class, + TraverserApiTest.class, + CustomizedPathsApiTest.class, + NeighborRankApiTest.class, + PersonalRankApiTest.class, }) public class ApiTestSuite { } diff --git a/src/test/java/com/baidu/hugegraph/api/CustomizedPathsApiTest.java b/src/test/java/com/baidu/hugegraph/api/CustomizedPathsApiTest.java new file mode 100644 index 00000000..1a7f38fa --- /dev/null +++ b/src/test/java/com/baidu/hugegraph/api/CustomizedPathsApiTest.java @@ -0,0 +1,371 @@ +/* + * Copyright 2017 HugeGraph Authors + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with this + * work for additional information regarding copyright ownership. The ASF + * licenses this file to You under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +package com.baidu.hugegraph.api; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +import org.junit.After; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.baidu.hugegraph.api.traverser.structure.CustomizedPaths; +import com.baidu.hugegraph.api.traverser.structure.PathsRequest; +import com.baidu.hugegraph.driver.SchemaManager; +import com.baidu.hugegraph.exception.ServerException; +import com.baidu.hugegraph.structure.constant.Direction; +import com.baidu.hugegraph.structure.graph.Vertex; +import com.baidu.hugegraph.structure.schema.EdgeLabel; +import com.baidu.hugegraph.testutil.Assert; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; + +public class CustomizedPathsApiTest extends BaseApiTest { + + @BeforeClass + public static void prepareSchemaAndGraph() { + BaseApiTest.initPropertyKey(); + BaseApiTest.initVertexLabel(); + BaseApiTest.initEdgeLabel(); + BaseApiTest.initIndexLabel(); + BaseApiTest.initVertex(); + BaseApiTest.initEdge(); + } + + @Before + public void setup() { + initEdgesWithWeights(); + } + + @After + public void teardown() { + removeEdgesWithWeights(); + } + + @Test + public void testCustomizedPathsSourceLabelProperty() { + Object markoId = getVertexId("person", "name", "marko"); + Object joshId = getVertexId("person", "name", "josh"); + Object rippleId = getVertexId("software", "name", "ripple"); + Object lopId = getVertexId("software", "name", "lop"); + + PathsRequest.Builder builder = new PathsRequest.Builder(); + builder.sources().label("person").property("name", "marko"); + builder.steps().direction(Direction.OUT).labels("knows1") + .weightBy("weight").degree(-1); + builder.steps().direction(Direction.OUT).labels("created1") + .weightBy("weight").degree(-1); + builder.sortBy(PathsRequest.SortBy.INCR).withVertex(true) + .capacity(-1).limit(-1); + PathsRequest request = builder.build(); + + CustomizedPaths customizedPaths = customizedPathsAPI.post(request); + List paths = customizedPaths.paths(); + + Assert.assertEquals(2, paths.size()); + + List path1 = ImmutableList.of(markoId, joshId, lopId); + List path2 = ImmutableList.of(markoId, joshId, rippleId); + Assert.assertEquals(path1, paths.get(0).objects()); + Assert.assertEquals(path2, paths.get(1).objects()); + + List weights1 = ImmutableList.of(1.0D, 0.4D); + List weights2 = ImmutableList.of(1.0D, 1.0D); + Assert.assertEquals(weights1, paths.get(0).weights()); + Assert.assertEquals(weights2, paths.get(1).weights()); + + Set vertices = customizedPaths.vertices().stream() + .map(Vertex::id) + .collect(Collectors.toSet()); + Assert.assertEquals(4, vertices.size()); + Set expectedVertices = ImmutableSet.of(markoId, lopId, + rippleId, joshId); + Assert.assertEquals(expectedVertices, vertices); + } + + @Test + public void testCustomizedPathsSourceIds() { + Object markoId = getVertexId("person", "name", "marko"); + Object lopId = getVertexId("software", "name", "lop"); + Object peterId = getVertexId("person", "name", "peter"); + + PathsRequest.Builder builder = new PathsRequest.Builder(); + builder.sources().ids(markoId, peterId); + builder.steps().direction(Direction.OUT).labels("created1") + .weightBy("weight").degree(-1); + builder.sortBy(PathsRequest.SortBy.INCR).withVertex(true) + .capacity(-1).limit(-1); + PathsRequest request = builder.build(); + + CustomizedPaths customizedPaths = customizedPathsAPI.post(request); + List paths = customizedPaths.paths(); + + Assert.assertEquals(2, paths.size()); + + List path1 = ImmutableList.of(markoId, lopId); + List path2 = ImmutableList.of(peterId, lopId); + List> expectedPaths = ImmutableList.of(path1, path2); + Assert.assertTrue(expectedPaths.contains(paths.get(0).objects())); + Assert.assertTrue(expectedPaths.contains(paths.get(1).objects())); + + List weights1 = ImmutableList.of(0.2D); + List weights2 = ImmutableList.of(0.4D); + List> expectedWeights = ImmutableList.of(weights1, + weights2); + Assert.assertTrue(expectedWeights.contains(paths.get(0).weights())); + Assert.assertTrue(expectedWeights.contains(paths.get(1).weights())); + + Set vertices = customizedPaths.vertices().stream() + .map(Vertex::id) + .collect(Collectors.toSet()); + Assert.assertEquals(3, vertices.size()); + Set expectedVertices = ImmutableSet.of(markoId, lopId, peterId); + Assert.assertEquals(expectedVertices, vertices); + } + + @Test + public void testCustomizedPathsSourceLabelPropertyMultiValue() { + Object markoId = getVertexId("person", "name", "marko"); + Object lopId = getVertexId("software", "name", "lop"); + Object peterId = getVertexId("person", "name", "peter"); + + PathsRequest.Builder builder = new PathsRequest.Builder(); + List names = ImmutableList.of("marko", "peter"); + builder.sources().label("person").property("name", names); + builder.steps().direction(Direction.OUT).labels("created1") + .weightBy("weight").degree(-1); + builder.sortBy(PathsRequest.SortBy.INCR).withVertex(true) + .capacity(-1).limit(-1); + PathsRequest request = builder.build(); + + CustomizedPaths customizedPaths = customizedPathsAPI.post(request); + List paths = customizedPaths.paths(); + + Assert.assertEquals(2, paths.size()); + + List path1 = ImmutableList.of(markoId, lopId); + List path2 = ImmutableList.of(peterId, lopId); + List> expectedPaths = ImmutableList.of(path1, path2); + Assert.assertTrue(expectedPaths.contains(paths.get(0).objects())); + Assert.assertTrue(expectedPaths.contains(paths.get(1).objects())); + + List weights1 = ImmutableList.of(0.2D); + List weights2 = ImmutableList.of(0.4D); + List> expectedWeights = ImmutableList.of(weights1, + weights2); + Assert.assertTrue(expectedWeights.contains(paths.get(0).weights())); + Assert.assertTrue(expectedWeights.contains(paths.get(1).weights())); + + Set vertices = customizedPaths.vertices().stream() + .map(Vertex::id) + .collect(Collectors.toSet()); + Assert.assertEquals(3, vertices.size()); + Set expectedVertices = ImmutableSet.of(markoId, lopId, peterId); + Assert.assertEquals(expectedVertices, vertices); + } + + @Test + public void testCustomizedPathsWithSample() { + Object markoId = getVertexId("person", "name", "marko"); + Object joshId = getVertexId("person", "name", "josh"); + Object rippleId = getVertexId("software", "name", "ripple"); + Object lopId = getVertexId("software", "name", "lop"); + + PathsRequest.Builder builder = new PathsRequest.Builder(); + builder.sources().label("person").property("name", "marko"); + builder.steps().direction(Direction.OUT).labels("knows1") + .weightBy("weight").degree(-1); + builder.steps().direction(Direction.OUT).labels("created1") + .weightBy("weight").degree(-1).sample(1); + builder.sortBy(PathsRequest.SortBy.INCR).withVertex(true) + .capacity(-1).limit(-1); + PathsRequest request = builder.build(); + + CustomizedPaths customizedPaths = customizedPathsAPI.post(request); + List paths = customizedPaths.paths(); + + Assert.assertEquals(1, paths.size()); + + List path1 = ImmutableList.of(markoId, joshId, rippleId); + List path2 = ImmutableList.of(markoId, joshId, lopId); + List> expectedPaths = ImmutableList.of(path1, path2); + Assert.assertTrue(expectedPaths.contains(paths.get(0).objects())); + + List weights1 = ImmutableList.of(1D, 0.4D); + List weights2 = ImmutableList.of(1D, 1D); + + Assert.assertTrue(weights1.equals(paths.get(0).weights()) || + weights2.equals(paths.get(0).weights())); + + Set vertices = customizedPaths.vertices().stream() + .map(Vertex::id) + .collect(Collectors.toSet()); + Assert.assertEquals(3, vertices.size()); + Assert.assertTrue(path1.containsAll(vertices) || + path2.containsAll(vertices)); + } + + @Test + public void testCustomizedPathsWithDecr() { + Object markoId = getVertexId("person", "name", "marko"); + Object joshId = getVertexId("person", "name", "josh"); + Object rippleId = getVertexId("software", "name", "ripple"); + Object lopId = getVertexId("software", "name", "lop"); + + PathsRequest.Builder builder = new PathsRequest.Builder(); + builder.sources().label("person").property("name", "marko"); + builder.steps().direction(Direction.OUT).labels("knows1") + .weightBy("weight").degree(-1); + builder.steps().direction(Direction.OUT).labels("created1") + .weightBy("weight").degree(-1); + builder.sortBy(PathsRequest.SortBy.DECR).withVertex(true) + .capacity(-1).limit(-1); + PathsRequest request = builder.build(); + + CustomizedPaths customizedPaths = customizedPathsAPI.post(request); + List paths = customizedPaths.paths(); + + Assert.assertEquals(2, paths.size()); + + List path1 = ImmutableList.of(markoId, joshId, rippleId); + List path2 = ImmutableList.of(markoId, joshId, lopId); + Assert.assertEquals(path1, paths.get(0).objects()); + Assert.assertEquals(path2, paths.get(1).objects()); + + List weights1 = ImmutableList.of(1.0D, 1.0D); + List weights2 = ImmutableList.of(1.0D, 0.4D); + Assert.assertEquals(weights1, paths.get(0).weights()); + Assert.assertEquals(weights2, paths.get(1).weights()); + + Set vertices = customizedPaths.vertices().stream() + .map(Vertex::id) + .collect(Collectors.toSet()); + Assert.assertEquals(4, vertices.size()); + Set expectedVertices = ImmutableSet.of(markoId, lopId, + rippleId, joshId); + Assert.assertEquals(expectedVertices, vertices); + } + + @Test + public void testCustomizedPathsWithLimit() { + Object markoId = getVertexId("person", "name", "marko"); + Object joshId = getVertexId("person", "name", "josh"); + Object rippleId = getVertexId("software", "name", "ripple"); + Object lopId = getVertexId("software", "name", "lop"); + + PathsRequest.Builder builder = new PathsRequest.Builder(); + builder.sources().label("person").property("name", "marko"); + builder.steps().direction(Direction.OUT).labels("knows1") + .weightBy("weight").degree(-1); + builder.steps().direction(Direction.OUT).labels("created1") + .weightBy("weight").degree(-1); + builder.sortBy(PathsRequest.SortBy.INCR).withVertex(true) + .capacity(-1).limit(1); + PathsRequest request = builder.build(); + + CustomizedPaths customizedPaths = customizedPathsAPI.post(request); + List paths = customizedPaths.paths(); + + Assert.assertEquals(1, paths.size()); + + List path1 = ImmutableList.of(markoId, joshId, lopId); + List path2 = ImmutableList.of(markoId, joshId, rippleId); + List> expectedPaths = ImmutableList.of(path1, path2); + Assert.assertTrue(expectedPaths.contains(paths.get(0).objects())); + + List weights1 = ImmutableList.of(1.0D, 0.4D); + List weights2 = ImmutableList.of(1.0D, 1.0D); + List> expectedWeights = ImmutableList.of(weights1, + weights2); + Assert.assertTrue(expectedWeights.contains(paths.get(0).weights())); + + Set vertices = customizedPaths.vertices().stream() + .map(Vertex::id) + .collect(Collectors.toSet()); + Assert.assertEquals(3, vertices.size()); + Set vertices1 = ImmutableSet.of(markoId, lopId, joshId); + Set vertices2 = ImmutableSet.of(markoId, lopId, rippleId); + Set> expectedVertices = ImmutableSet.of(vertices1, vertices2); + Assert.assertTrue(expectedVertices.contains(vertices)); + } + + @Test + public void testCustomizedPathsWithCapacity() { + PathsRequest.Builder builder = new PathsRequest.Builder(); + builder.sources().label("person").property("name", "marko"); + builder.steps().direction(Direction.OUT).labels("knows1") + .weightBy("weight").degree(-1); + builder.steps().direction(Direction.OUT).labels("created1") + .weightBy("weight").degree(-1); + builder.sortBy(PathsRequest.SortBy.INCR).withVertex(true) + .capacity(1).limit(-1); + PathsRequest request = builder.build(); + + Assert.assertThrows(ServerException.class, () -> { + customizedPathsAPI.post(request); + }); + } + + private static void initEdgesWithWeights() { + SchemaManager schema = schema(); + schema.edgeLabel("knows1") + .sourceLabel("person") + .targetLabel("person") + .properties("date", "weight") + .nullableKeys("weight") + .ifNotExist() + .create(); + + schema.edgeLabel("created1") + .sourceLabel("person") + .targetLabel("software") + .properties("date", "weight") + .nullableKeys("weight") + .ifNotExist() + .create(); + + Vertex marko = getVertex("person", "name", "marko"); + Vertex vadas = getVertex("person", "name", "vadas"); + Vertex lop = getVertex("software", "name", "lop"); + Vertex josh = getVertex("person", "name", "josh"); + Vertex ripple = getVertex("software", "name", "ripple"); + Vertex peter = getVertex("person", "name", "peter"); + + marko.addEdge("knows1", vadas, "date", "20160110", "weight", 0.5); + marko.addEdge("knows1", josh, "date", "20130220", "weight", 1.0); + marko.addEdge("created1", lop, "date", "20171210", "weight", 0.4); + josh.addEdge("created1", lop, "date", "20091111", "weight", 0.4); + josh.addEdge("created1", ripple, "date", "20171210", "weight", 1.0); + peter.addEdge("created1", lop, "date", "20170324", "weight", 0.2); + } + + private static void removeEdgesWithWeights() { + List elTaskIds = new ArrayList<>(); + EdgeLabel knows1 = schema().getEdgeLabel("knows1"); + EdgeLabel created1 = schema().getEdgeLabel("created1"); + ImmutableList.of(knows1, created1).forEach(edgeLabel -> { + elTaskIds.add(edgeLabelAPI.delete(edgeLabel.name())); + }); + elTaskIds.forEach(BaseApiTest::waitUntilTaskCompleted); + } +} diff --git a/src/test/java/com/baidu/hugegraph/api/NeighborRankApiTest.java b/src/test/java/com/baidu/hugegraph/api/NeighborRankApiTest.java new file mode 100644 index 00000000..35719033 --- /dev/null +++ b/src/test/java/com/baidu/hugegraph/api/NeighborRankApiTest.java @@ -0,0 +1,348 @@ +/* + * Copyright 2017 HugeGraph Authors + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with this + * work for additional information regarding copyright ownership. The ASF + * licenses this file to You under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +package com.baidu.hugegraph.api; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.After; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.baidu.hugegraph.api.traverser.NeighborRankAPI; +import com.baidu.hugegraph.api.traverser.structure.Ranks; +import com.baidu.hugegraph.driver.GraphManager; +import com.baidu.hugegraph.driver.SchemaManager; +import com.baidu.hugegraph.exception.ServerException; +import com.baidu.hugegraph.structure.constant.Direction; +import com.baidu.hugegraph.structure.constant.T; +import com.baidu.hugegraph.structure.graph.Vertex; +import com.baidu.hugegraph.testutil.Assert; +import com.google.common.collect.ImmutableMap; + +public class NeighborRankApiTest extends BaseApiTest { + + @BeforeClass + public static void prepareSchemaAndGraph() { + BaseApiTest.initPropertyKey(); + } + + @Before + public void setup() { + initNeighborRankGraph(); + } + + @After + public void teardown() { + clearNeighborRankGraph(); + } + + @Test + public void testNeighborRank() { + NeighborRankAPI.Request.Builder builder; + builder = NeighborRankAPI.Request.builder(); + builder.source("O"); + builder.steps().direction(Direction.OUT).degree(-1).top(10); + builder.steps().direction(Direction.OUT).degree(-1).top(10); + builder.steps().direction(Direction.OUT).degree(-1).top(10); + builder.alpha(0.9).capacity(-1); + NeighborRankAPI.Request request = builder.build(); + + List ranks = neighborRankAPI.post(request); + Assert.assertEquals(4, ranks.size()); + Assert.assertEquals(ImmutableMap.of("O", 1.0D), ranks.get(0)); + Assert.assertEquals(ImmutableMap.of("B", 0.4305D, "A", 0.3D, "C", 0.3D), + ranks.get(1)); + Assert.assertEquals(ImmutableMap.builder() + .put("G", 0.17550000000000002D) + .put("H", 0.17550000000000002D) + .put("I", 0.135D) + .put("J", 0.135D) + .put("E", 0.09000000000000001D) + .put("F", 0.09000000000000001D) + .build(), + ranks.get(2)); + Assert.assertEquals(ImmutableMap.of("M", 0.15795D, + "K", 0.08100000000000002D, + "L", 0.04050000000000001D), + ranks.get(3)); + } + + @Test + public void testNeighborRankWithOtherAlpha() { + NeighborRankAPI.Request.Builder builder; + builder = NeighborRankAPI.Request.builder(); + builder.source("O"); + builder.steps().direction(Direction.OUT).degree(-1).top(10); + builder.steps().direction(Direction.OUT).degree(-1).top(10); + builder.steps().direction(Direction.OUT).degree(-1).top(10); + builder.alpha(1.0).capacity(-1); + NeighborRankAPI.Request request = builder.build(); + + List ranks = neighborRankAPI.post(request); + Assert.assertEquals(4, ranks.size()); + Assert.assertEquals(ImmutableMap.of("O", 1.0D), ranks.get(0)); + Assert.assertEquals(ImmutableMap.of("B", 0.5D, + "A", 0.3333333333333333D, + "C", 0.3333333333333333D), + ranks.get(1)); + Assert.assertEquals(ImmutableMap.builder() + .put("G", 0.2222222222222222D) + .put("H", 0.2222222222222222D) + .put("I", 0.16666666666666666D) + .put("J", 0.16666666666666666D) + .put("E", 0.1111111111111111D) + .put("F", 0.1111111111111111D) + .build(), + ranks.get(2)); + Assert.assertEquals(ImmutableMap.of("M", 0.2222222222222222D, + "K", 0.1111111111111111D, + "L", 0.05555555555555555D), + ranks.get(3)); + } + + @Test + public void testNeighborRankWithDirection() { + NeighborRankAPI.Request.Builder builder; + builder = NeighborRankAPI.Request.builder(); + builder.source("O"); + builder.steps().direction(Direction.BOTH); + builder.steps().direction(Direction.IN); + builder.steps().direction(Direction.OUT); + builder.alpha(0.9).capacity(-1); + NeighborRankAPI.Request request = builder.build(); + + List ranks = neighborRankAPI.post(request); + Assert.assertEquals(4, ranks.size()); + Assert.assertEquals(ImmutableMap.of("O", 1.0D), ranks.get(0)); + Assert.assertEquals(ImmutableMap.of("A", 0.32625000000000004D, + "B", 0.27056250000000004D, + "C", 0.225D, + "D", 0.225D), + ranks.get(1)); + Assert.assertEquals(ImmutableMap.of("F", 0.10125D), + ranks.get(2)); + Assert.assertEquals(ImmutableMap.of("L", 0.045562500000000006D), + ranks.get(3)); + } + + @Test + public void testNeighborRankWithLabels() { + NeighborRankAPI.Request.Builder builder; + builder = NeighborRankAPI.Request.builder(); + builder.source("O"); + builder.steps().labels("follow").direction(Direction.OUT); + builder.steps().labels("like").direction(Direction.OUT); + builder.steps().labels("directedBy").direction(Direction.OUT); + builder.alpha(0.9).capacity(-1); + NeighborRankAPI.Request request = builder.build(); + + List ranks = neighborRankAPI.post(request); + Assert.assertEquals(4, ranks.size()); + Assert.assertEquals(ImmutableMap.of("O", 1.0D), ranks.get(0)); + Assert.assertEquals(ImmutableMap.of("B", 0.36075D, + "A", 0.3D, + "C", 0.3D), + ranks.get(1)); + Assert.assertEquals(ImmutableMap.builder() + .put("E", 0.135) + .put("F", 0.135) + .put("G", 0.135) + .put("H", 0.135) + .put("I", 0.135) + .put("J", 0.135) + .build(), + ranks.get(2)); + Assert.assertEquals(ImmutableMap.of("K", 0.12150000000000001D, + "M", 0.12150000000000001D, + "L", 0.060750000000000005D), + ranks.get(3)); + } + + @Test + public void testNeighborRankWithTop() { + NeighborRankAPI.Request.Builder builder; + builder = NeighborRankAPI.Request.builder(); + builder.source("O"); + builder.steps().direction(Direction.OUT).degree(-1).top(2); + builder.steps().direction(Direction.OUT).degree(-1).top(3); + builder.steps().direction(Direction.OUT).degree(-1).top(2); + builder.alpha(0.9).capacity(-1); + NeighborRankAPI.Request request = builder.build(); + + List ranks = neighborRankAPI.post(request); + Assert.assertEquals(4, ranks.size()); + Assert.assertEquals(ImmutableMap.of("O", 1.0D), ranks.get(0)); + Assert.assertEquals(ImmutableMap.of("B", 0.4305D, "A", 0.3D), + ranks.get(1)); + Assert.assertEquals(ImmutableMap.of("G", 0.17550000000000002D, + "H", 0.17550000000000002D, + "I", 0.135D), + ranks.get(2)); + Assert.assertEquals(ImmutableMap.of("M", 0.15795D, + "K", 0.08100000000000002D), + ranks.get(3)); + } + + @Test + public void testNeighborRankWithDegree() { + NeighborRankAPI.Request.Builder builder; + builder = NeighborRankAPI.Request.builder(); + builder.source("O"); + builder.steps().direction(Direction.OUT).degree(2); + builder.steps().direction(Direction.OUT).degree(1); + builder.steps().direction(Direction.OUT).degree(1); + builder.alpha(0.9).capacity(-1); + NeighborRankAPI.Request request = builder.build(); + + List ranks = neighborRankAPI.post(request); + Assert.assertEquals(4, ranks.size()); + Assert.assertEquals(ImmutableMap.of("O", 1.0D), ranks.get(0)); + Assert.assertEquals(ImmutableMap.of("B", 0.855D, "A", 0.45D), + ranks.get(1)); + Assert.assertEquals(ImmutableMap.of("G", 0.7695D), ranks.get(2)); + Assert.assertEquals(ImmutableMap.of("M", 0.69255D), ranks.get(3)); + + builder = NeighborRankAPI.Request.builder(); + builder.source("O"); + builder.steps().direction(Direction.OUT).degree(2); + builder.steps().direction(Direction.OUT).degree(2); + builder.steps().direction(Direction.OUT).degree(1); + builder.alpha(0.9).capacity(-1); + request = builder.build(); + + ranks = neighborRankAPI.post(request); + Assert.assertEquals(4, ranks.size()); + Assert.assertEquals(ImmutableMap.of("O", 1.0D), ranks.get(0)); + Assert.assertEquals(ImmutableMap.of("B", 0.6525000000000001D, + "A", 0.45D), + ranks.get(1)); + Assert.assertEquals(ImmutableMap.of("G", 0.293625D, + "H", 0.293625D, + "E", 0.2025D), + ranks.get(2)); + Assert.assertEquals(ImmutableMap.of("M", 0.2642625D, + "K", 0.18225000000000002D), + ranks.get(3)); + } + + @Test + public void testNeighborRankWithCapacity() { + NeighborRankAPI.Request.Builder builder; + builder = NeighborRankAPI.Request.builder(); + builder.source("O"); + builder.steps().direction(Direction.OUT); + builder.steps().direction(Direction.OUT); + builder.steps().direction(Direction.OUT); + builder.alpha(0.9).capacity(1); + NeighborRankAPI.Request request = builder.build(); + + Assert.assertThrows(ServerException.class, () -> { + neighborRankAPI.post(request); + }); + } + + private static void initNeighborRankGraph() { + GraphManager graph = graph(); + SchemaManager schema = schema(); + + schema.vertexLabel("person") + .properties("name") + .useCustomizeStringId() + .ifNotExist() + .create(); + + schema.vertexLabel("movie") + .properties("name") + .useCustomizeStringId() + .ifNotExist() + .create(); + + schema.edgeLabel("follow") + .sourceLabel("person") + .targetLabel("person") + .ifNotExist() + .create(); + + schema.edgeLabel("like") + .sourceLabel("person") + .targetLabel("movie") + .ifNotExist() + .create(); + + schema.edgeLabel("directedBy") + .sourceLabel("movie") + .targetLabel("person") + .ifNotExist() + .create(); + + Vertex O = graph.addVertex(T.label, "person", T.id, "O", "name", "O"); + + Vertex A = graph.addVertex(T.label, "person", T.id, "A", "name", "A"); + Vertex B = graph.addVertex(T.label, "person", T.id, "B", "name", "B"); + Vertex C = graph.addVertex(T.label, "person", T.id, "C", "name", "C"); + Vertex D = graph.addVertex(T.label, "person", T.id, "D", "name", "D"); + + Vertex E = graph.addVertex(T.label, "movie", T.id, "E", "name", "E"); + Vertex F = graph.addVertex(T.label, "movie", T.id, "F", "name", "F"); + Vertex G = graph.addVertex(T.label, "movie", T.id, "G", "name", "G"); + Vertex H = graph.addVertex(T.label, "movie", T.id, "H", "name", "H"); + Vertex I = graph.addVertex(T.label, "movie", T.id, "I", "name", "I"); + Vertex J = graph.addVertex(T.label, "movie", T.id, "J", "name", "J"); + + Vertex K = graph.addVertex(T.label, "person", T.id, "K", "name", "K"); + Vertex L = graph.addVertex(T.label, "person", T.id, "L", "name", "L"); + Vertex M = graph.addVertex(T.label, "person", T.id, "M", "name", "M"); + + O.addEdge("follow", A); + O.addEdge("follow", B); + O.addEdge("follow", C); + D.addEdge("follow", O); + + A.addEdge("follow", B); + A.addEdge("like", E); + A.addEdge("like", F); + + B.addEdge("like", G); + B.addEdge("like", H); + + C.addEdge("like", I); + C.addEdge("like", J); + + E.addEdge("directedBy", K); + F.addEdge("directedBy", B); + F.addEdge("directedBy", L); + + G.addEdge("directedBy", M); + } + + private static void clearNeighborRankGraph() { + List taskIds = new ArrayList<>(); + taskIds.add(edgeLabelAPI.delete("directedBy")); + taskIds.add(edgeLabelAPI.delete("like")); + taskIds.add(edgeLabelAPI.delete("follow")); + taskIds.forEach(BaseApiTest::waitUntilTaskCompleted); + taskIds.clear(); + taskIds.add(vertexLabelAPI.delete("movie")); + taskIds.add(vertexLabelAPI.delete("person")); + taskIds.forEach(BaseApiTest::waitUntilTaskCompleted); + } +} diff --git a/src/test/java/com/baidu/hugegraph/api/PersonalRankApiTest.java b/src/test/java/com/baidu/hugegraph/api/PersonalRankApiTest.java new file mode 100644 index 00000000..290e3419 --- /dev/null +++ b/src/test/java/com/baidu/hugegraph/api/PersonalRankApiTest.java @@ -0,0 +1,255 @@ +/* + * Copyright 2017 HugeGraph Authors + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with this + * work for additional information regarding copyright ownership. The ASF + * licenses this file to You under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +package com.baidu.hugegraph.api; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.junit.After; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.baidu.hugegraph.api.traverser.PersonalRankAPI; +import com.baidu.hugegraph.driver.GraphManager; +import com.baidu.hugegraph.driver.SchemaManager; +import com.baidu.hugegraph.structure.constant.T; +import com.baidu.hugegraph.structure.graph.Vertex; +import com.baidu.hugegraph.testutil.Assert; +import com.google.common.collect.ImmutableMap; + +public class PersonalRankApiTest extends BaseApiTest { + + @BeforeClass + public static void prepareSchemaAndGraph() { + BaseApiTest.initPropertyKey(); + } + + @Before + public void setup() { + initPersonalRankGraph(); + } + + @After + public void teardown() { + clearPersonalRankGraph(); + } + + @Test + public void testPersonalRank() { + PersonalRankAPI.Request.Builder builder; + builder = PersonalRankAPI.Request.builder(); + builder.source("A").label("like").alpha(0.9).maxDepth(50); + PersonalRankAPI.Request request = builder.build(); + + Map ranks = personalRankAPI.post(request); + Assert.assertEquals(ImmutableMap.of("B", 0.2065750574989044D, + "C", 0.09839507219265439D, + "d", 0.08959757100230095D, + "b", 0.04589958822642998D), + ranks); + } + + @Test + public void testPersonalRankWithWithLabel() { + PersonalRankAPI.Request.Builder builder; + builder = PersonalRankAPI.Request.builder(); + builder.source("A").label("like").alpha(0.9).maxDepth(50) + .withLabel(PersonalRankAPI.Request.WithLabel.SAME_LABEL); + PersonalRankAPI.Request request = builder.build(); + + Map ranks = personalRankAPI.post(request); + Assert.assertEquals(ImmutableMap.of("B", 0.2065750574989044D, + "C", 0.09839507219265439D), + ranks); + + builder = PersonalRankAPI.Request.builder(); + builder.source("A").label("like").alpha(0.9).maxDepth(50) + .withLabel(PersonalRankAPI.Request.WithLabel.OTHER_LABEL); + request = builder.build(); + + ranks = personalRankAPI.post(request); + Assert.assertEquals(ImmutableMap.of("d", 0.08959757100230095D, + "b", 0.04589958822642998D), + ranks); + } + + @Test + public void testPersonalRankWithOtherAlpha() { + PersonalRankAPI.Request.Builder builder; + builder = PersonalRankAPI.Request.builder(); + builder.source("A").label("like").alpha(1).maxDepth(50); + PersonalRankAPI.Request request = builder.build(); + + Map ranks = personalRankAPI.post(request); + Assert.assertEquals(ImmutableMap.of("B", 0.5D, + "C", 0.24999999999999956D, + "b", 0.0D, + "d", 0.0D), + ranks); + } + + @Test + public void testPersonalRankWithDegree() { + PersonalRankAPI.Request.Builder builder; + builder = PersonalRankAPI.Request.builder(); + + builder.source("A").label("like").alpha(0.9).degree(1).maxDepth(1); + PersonalRankAPI.Request request = builder.build(); + + // Removed root and direct neighbors of root + Map ranks = personalRankAPI.post(request); + Assert.assertEquals(ImmutableMap.of(), ranks); + + builder.source("A").label("like").alpha(0.9).degree(1).maxDepth(2); + request = builder.build(); + + ranks = personalRankAPI.post(request); + Assert.assertEquals(ImmutableMap.of(), ranks); + + builder.source("A").label("like").alpha(0.9).degree(2).maxDepth(1); + request = builder.build(); + + ranks = personalRankAPI.post(request); + Assert.assertEquals(ImmutableMap.of(), ranks); + + builder.source("A").label("like").alpha(0.9).degree(2).maxDepth(2); + request = builder.build(); + + ranks = personalRankAPI.post(request); + Assert.assertEquals(ImmutableMap.of("B", 0.405D), ranks); + } + + @Test + public void testPersonalRankWithLimit() { + PersonalRankAPI.Request.Builder builder; + builder = PersonalRankAPI.Request.builder(); + builder.source("A").label("like").alpha(0.9).limit(3).maxDepth(50); + PersonalRankAPI.Request request = builder.build(); + + Map ranks = personalRankAPI.post(request); + Assert.assertEquals(ImmutableMap.of("B", 0.2065750574989044D, + "C", 0.09839507219265439D, + "d", 0.08959757100230095D), + ranks); + } + + @Test + public void testPersonalRankWithMaxDepth() { + PersonalRankAPI.Request.Builder builder; + builder = PersonalRankAPI.Request.builder(); + builder.source("A").label("like").alpha(0.9).maxDepth(100); + PersonalRankAPI.Request request = builder.build(); + + Map ranks = personalRankAPI.post(request); + Assert.assertEquals(ImmutableMap.of("B", 0.2053607173863809D, + "C", 0.09778790213639266D, + "d", 0.09020474105856267D, + "b", 0.04620317325456084D), + ranks); + } + + @Test + public void testPersonalRankWithUnsorted() { + PersonalRankAPI.Request.Builder builder; + builder = PersonalRankAPI.Request.builder(); + builder.source("A").label("like").alpha(0.9).maxDepth(50).sorted(false); + PersonalRankAPI.Request request = builder.build(); + + Map ranks = personalRankAPI.post(request); + Assert.assertEquals(ImmutableMap.of("b", 0.04589958822642998D, + "B", 0.2065750574989044D, + "C", 0.09839507219265439D, + "d", 0.08959757100230095D), + ranks); + } + + @Test + public void testPersonalRankWithIsolatedVertex() { + Vertex isolate = graph().addVertex(T.label, "person", T.id, "isolate", + "name", "isolate-vertex"); + + PersonalRankAPI.Request.Builder builder; + builder = PersonalRankAPI.Request.builder(); + builder.source("isolate").label("like").alpha(0.9).maxDepth(50); + PersonalRankAPI.Request request = builder.build(); + + Map ranks = personalRankAPI.post(request); + Assert.assertEquals(ImmutableMap.of(), ranks); + + graph().removeVertex(isolate.id()); + } + + private static void initPersonalRankGraph() { + GraphManager graph = graph(); + SchemaManager schema = schema(); + + schema.propertyKey("name").asText().ifNotExist().create(); + + schema.vertexLabel("person") + .properties("name") + .useCustomizeStringId() + .ifNotExist() + .create(); + + schema.vertexLabel("movie") + .properties("name") + .useCustomizeStringId() + .ifNotExist() + .create(); + + schema.edgeLabel("like") + .sourceLabel("person") + .targetLabel("movie") + .ifNotExist() + .create(); + + Vertex A = graph.addVertex(T.label, "person", T.id, "A", "name", "A"); + Vertex B = graph.addVertex(T.label, "person", T.id, "B", "name", "B"); + Vertex C = graph.addVertex(T.label, "person", T.id, "C", "name", "C"); + + Vertex a = graph.addVertex(T.label, "movie", T.id, "a", "name", "a"); + Vertex b = graph.addVertex(T.label, "movie", T.id, "b", "name", "b"); + Vertex c = graph.addVertex(T.label, "movie", T.id, "c", "name", "c"); + Vertex d = graph.addVertex(T.label, "movie", T.id, "d", "name", "d"); + + A.addEdge("like", a); + A.addEdge("like", c); + + B.addEdge("like", a); + B.addEdge("like", b); + B.addEdge("like", c); + B.addEdge("like", d); + + C.addEdge("like", c); + C.addEdge("like", d); + } + + private void clearPersonalRankGraph() { + List taskIds = new ArrayList<>(); + taskIds.add(edgeLabelAPI.delete("like")); + taskIds.forEach(BaseApiTest::waitUntilTaskCompleted); + taskIds.clear(); + taskIds.add(vertexLabelAPI.delete("movie")); + taskIds.add(vertexLabelAPI.delete("person")); + taskIds.forEach(BaseApiTest::waitUntilTaskCompleted); + } +} diff --git a/src/test/java/com/baidu/hugegraph/api/TraverserApiTest.java b/src/test/java/com/baidu/hugegraph/api/TraverserApiTest.java index 064ab5da..0babef18 100644 --- a/src/test/java/com/baidu/hugegraph/api/TraverserApiTest.java +++ b/src/test/java/com/baidu/hugegraph/api/TraverserApiTest.java @@ -19,6 +19,8 @@ package com.baidu.hugegraph.api; +import static com.baidu.hugegraph.structure.constant.Traverser.DEFAULT_PAGE_LIMIT; + import java.util.ArrayList; import java.util.LinkedList; import java.util.List; @@ -53,8 +55,6 @@ import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; -import static com.baidu.hugegraph.structure.constant.Traverser.DEFAULT_PAGE_LIMIT; - public class TraverserApiTest extends BaseApiTest { @BeforeClass @@ -598,291 +598,6 @@ public void testRaysWithCapacity() { }); } - @Test - public void testCustomizedPathsSourceLabelProperty() { - initEdgesWithWeights(); - - Object markoId = getVertexId("person", "name", "marko"); - Object joshId = getVertexId("person", "name", "josh"); - Object rippleId = getVertexId("software", "name", "ripple"); - Object lopId = getVertexId("software", "name", "lop"); - - PathsRequest.Builder builder = new PathsRequest.Builder(); - builder.sources().label("person").property("name", "marko"); - builder.steps().direction(Direction.OUT).labels("knows1") - .weightBy("weight").degree(-1); - builder.steps().direction(Direction.OUT).labels("created1") - .weightBy("weight").degree(-1); - builder.sortBy(PathsRequest.SortBy.INCR).withVertex(true) - .capacity(-1).limit(-1); - PathsRequest request = builder.build(); - - CustomizedPaths customizedPaths = customizedPathsAPI.post(request); - List paths = customizedPaths.paths(); - - Assert.assertEquals(2, paths.size()); - - List path1 = ImmutableList.of(markoId, joshId, lopId); - List path2 = ImmutableList.of(markoId, joshId, rippleId); - Assert.assertEquals(path1, paths.get(0).objects()); - Assert.assertEquals(path2, paths.get(1).objects()); - - List weights1 = ImmutableList.of(1.0D, 0.4D); - List weights2 = ImmutableList.of(1.0D, 1.0D); - Assert.assertEquals(weights1, paths.get(0).weights()); - Assert.assertEquals(weights2, paths.get(1).weights()); - - Set vertices = customizedPaths.vertices().stream() - .map(Vertex::id) - .collect(Collectors.toSet()); - Assert.assertEquals(4, vertices.size()); - Set expectedVertices = ImmutableSet.of(markoId, lopId, - rippleId, joshId); - Assert.assertEquals(expectedVertices, vertices); - removeEdgesWithWeights(); - } - - @Test - public void testCustomizedPathsSourceIds() { - initEdgesWithWeights(); - - Object markoId = getVertexId("person", "name", "marko"); - Object lopId = getVertexId("software", "name", "lop"); - Object peterId = getVertexId("person", "name", "peter"); - - PathsRequest.Builder builder = new PathsRequest.Builder(); - builder.sources().ids(markoId, peterId); - builder.steps().direction(Direction.OUT).labels("created1") - .weightBy("weight").degree(-1); - builder.sortBy(PathsRequest.SortBy.INCR).withVertex(true) - .capacity(-1).limit(-1); - PathsRequest request = builder.build(); - - CustomizedPaths customizedPaths = customizedPathsAPI.post(request); - List paths = customizedPaths.paths(); - - Assert.assertEquals(2, paths.size()); - - List path1 = ImmutableList.of(markoId, lopId); - List path2 = ImmutableList.of(peterId, lopId); - List> expectedPaths = ImmutableList.of(path1, path2); - Assert.assertTrue(expectedPaths.contains(paths.get(0).objects())); - Assert.assertTrue(expectedPaths.contains(paths.get(1).objects())); - - List weights1 = ImmutableList.of(0.2D); - List weights2 = ImmutableList.of(0.4D); - List> expectedWeights = ImmutableList.of(weights1, - weights2); - Assert.assertTrue(expectedWeights.contains(paths.get(0).weights())); - Assert.assertTrue(expectedWeights.contains(paths.get(1).weights())); - - Set vertices = customizedPaths.vertices().stream() - .map(Vertex::id) - .collect(Collectors.toSet()); - Assert.assertEquals(3, vertices.size()); - Set expectedVertices = ImmutableSet.of(markoId, lopId, peterId); - Assert.assertEquals(expectedVertices, vertices); - removeEdgesWithWeights(); - } - - @Test - public void testCustomizedPathsSourceLabelPropertyMultiValue() { - initEdgesWithWeights(); - - Object markoId = getVertexId("person", "name", "marko"); - Object lopId = getVertexId("software", "name", "lop"); - Object peterId = getVertexId("person", "name", "peter"); - - PathsRequest.Builder builder = new PathsRequest.Builder(); - List names = ImmutableList.of("marko", "peter"); - builder.sources().label("person").property("name", names); - builder.steps().direction(Direction.OUT).labels("created1") - .weightBy("weight").degree(-1); - builder.sortBy(PathsRequest.SortBy.INCR).withVertex(true) - .capacity(-1).limit(-1); - PathsRequest request = builder.build(); - - CustomizedPaths customizedPaths = customizedPathsAPI.post(request); - List paths = customizedPaths.paths(); - - Assert.assertEquals(2, paths.size()); - - List path1 = ImmutableList.of(markoId, lopId); - List path2 = ImmutableList.of(peterId, lopId); - List> expectedPaths = ImmutableList.of(path1, path2); - Assert.assertTrue(expectedPaths.contains(paths.get(0).objects())); - Assert.assertTrue(expectedPaths.contains(paths.get(1).objects())); - - List weights1 = ImmutableList.of(0.2D); - List weights2 = ImmutableList.of(0.4D); - List> expectedWeights = ImmutableList.of(weights1, - weights2); - Assert.assertTrue(expectedWeights.contains(paths.get(0).weights())); - Assert.assertTrue(expectedWeights.contains(paths.get(1).weights())); - - Set vertices = customizedPaths.vertices().stream() - .map(Vertex::id) - .collect(Collectors.toSet()); - Assert.assertEquals(3, vertices.size()); - Set expectedVertices = ImmutableSet.of(markoId, lopId, peterId); - Assert.assertEquals(expectedVertices, vertices); - removeEdgesWithWeights(); - } - - @Test - public void testCustomizedPathsWithSample() { - initEdgesWithWeights(); - - Object markoId = getVertexId("person", "name", "marko"); - Object joshId = getVertexId("person", "name", "josh"); - Object rippleId = getVertexId("software", "name", "ripple"); - Object lopId = getVertexId("software", "name", "lop"); - - PathsRequest.Builder builder = new PathsRequest.Builder(); - builder.sources().label("person").property("name", "marko"); - builder.steps().direction(Direction.OUT).labels("knows1") - .weightBy("weight").degree(-1); - builder.steps().direction(Direction.OUT).labels("created1") - .weightBy("weight").degree(-1).sample(1); - builder.sortBy(PathsRequest.SortBy.INCR).withVertex(true) - .capacity(-1).limit(-1); - PathsRequest request = builder.build(); - - CustomizedPaths customizedPaths = customizedPathsAPI.post(request); - List paths = customizedPaths.paths(); - - Assert.assertEquals(1, paths.size()); - - List path1 = ImmutableList.of(markoId, joshId, rippleId); - List path2 = ImmutableList.of(markoId, joshId, lopId); - List> expectedPaths = ImmutableList.of(path1, path2); - Assert.assertTrue(expectedPaths.contains(paths.get(0).objects())); - - List weights1 = ImmutableList.of(1D, 0.4D); - List weights2 = ImmutableList.of(1D, 1D); - - Assert.assertTrue(weights1.equals(paths.get(0).weights()) || - weights2.equals(paths.get(0).weights())); - - Set vertices = customizedPaths.vertices().stream() - .map(Vertex::id) - .collect(Collectors.toSet()); - Assert.assertEquals(3, vertices.size()); - Assert.assertTrue(path1.containsAll(vertices) || - path2.containsAll(vertices)); - removeEdgesWithWeights(); - } - - @Test - public void testCustomizedPathsWithDecr() { - initEdgesWithWeights(); - - Object markoId = getVertexId("person", "name", "marko"); - Object joshId = getVertexId("person", "name", "josh"); - Object rippleId = getVertexId("software", "name", "ripple"); - Object lopId = getVertexId("software", "name", "lop"); - - PathsRequest.Builder builder = new PathsRequest.Builder(); - builder.sources().label("person").property("name", "marko"); - builder.steps().direction(Direction.OUT).labels("knows1") - .weightBy("weight").degree(-1); - builder.steps().direction(Direction.OUT).labels("created1") - .weightBy("weight").degree(-1); - builder.sortBy(PathsRequest.SortBy.DECR).withVertex(true) - .capacity(-1).limit(-1); - PathsRequest request = builder.build(); - - CustomizedPaths customizedPaths = customizedPathsAPI.post(request); - List paths = customizedPaths.paths(); - - Assert.assertEquals(2, paths.size()); - - List path1 = ImmutableList.of(markoId, joshId, rippleId); - List path2 = ImmutableList.of(markoId, joshId, lopId); - Assert.assertEquals(path1, paths.get(0).objects()); - Assert.assertEquals(path2, paths.get(1).objects()); - - List weights1 = ImmutableList.of(1.0D, 1.0D); - List weights2 = ImmutableList.of(1.0D, 0.4D); - Assert.assertEquals(weights1, paths.get(0).weights()); - Assert.assertEquals(weights2, paths.get(1).weights()); - - Set vertices = customizedPaths.vertices().stream() - .map(Vertex::id) - .collect(Collectors.toSet()); - Assert.assertEquals(4, vertices.size()); - Set expectedVertices = ImmutableSet.of(markoId, lopId, - rippleId, joshId); - Assert.assertEquals(expectedVertices, vertices); - removeEdgesWithWeights(); - } - - @Test - public void testCustomizedPathsWithLimit() { - initEdgesWithWeights(); - - Object markoId = getVertexId("person", "name", "marko"); - Object joshId = getVertexId("person", "name", "josh"); - Object rippleId = getVertexId("software", "name", "ripple"); - Object lopId = getVertexId("software", "name", "lop"); - - PathsRequest.Builder builder = new PathsRequest.Builder(); - builder.sources().label("person").property("name", "marko"); - builder.steps().direction(Direction.OUT).labels("knows1") - .weightBy("weight").degree(-1); - builder.steps().direction(Direction.OUT).labels("created1") - .weightBy("weight").degree(-1); - builder.sortBy(PathsRequest.SortBy.INCR).withVertex(true) - .capacity(-1).limit(1); - PathsRequest request = builder.build(); - - CustomizedPaths customizedPaths = customizedPathsAPI.post(request); - List paths = customizedPaths.paths(); - - Assert.assertEquals(1, paths.size()); - - List path1 = ImmutableList.of(markoId, joshId, lopId); - List path2 = ImmutableList.of(markoId, joshId, rippleId); - List> expectedPaths = ImmutableList.of(path1, path2); - Assert.assertTrue(expectedPaths.contains(paths.get(0).objects())); - - List weights1 = ImmutableList.of(1.0D, 0.4D); - List weights2 = ImmutableList.of(1.0D, 1.0D); - List> expectedWeights = ImmutableList.of(weights1, - weights2); - Assert.assertTrue(expectedWeights.contains(paths.get(0).weights())); - - Set vertices = customizedPaths.vertices().stream() - .map(Vertex::id) - .collect(Collectors.toSet()); - Assert.assertEquals(3, vertices.size()); - Set vertices1 = ImmutableSet.of(markoId, lopId, joshId); - Set vertices2 = ImmutableSet.of(markoId, lopId, rippleId); - Set> expectedVertices = ImmutableSet.of(vertices1, vertices2); - Assert.assertTrue(expectedVertices.contains(vertices)); - removeEdgesWithWeights(); - } - - @Test - public void testCustomizedPathsWithCapacity() { - initEdgesWithWeights(); - - PathsRequest.Builder builder = new PathsRequest.Builder(); - builder.sources().label("person").property("name", "marko"); - builder.steps().direction(Direction.OUT).labels("knows1") - .weightBy("weight").degree(-1); - builder.steps().direction(Direction.OUT).labels("created1") - .weightBy("weight").degree(-1); - builder.sortBy(PathsRequest.SortBy.INCR).withVertex(true) - .capacity(1).limit(-1); - PathsRequest request = builder.build(); - - Assert.assertThrows(ServerException.class, () -> { - customizedPathsAPI.post(request); - }); - removeEdgesWithWeights(); - } - @Test public void testCustomizedCrosspoints() { Object lopId = getVertexId("software", "name", "lop"); @@ -917,92 +632,6 @@ public void testCustomizedCrosspoints() { Assert.assertTrue(expectedVids.containsAll(vertices)); } - @Test - public void testNeighborRank() { - initNeighborRankGraph(); - - NeighborRankAPI.RankRequest.Builder builder; - builder = new NeighborRankAPI.RankRequest.Builder(); - builder.source("O"); - builder.steps().direction(Direction.OUT).degree(-1).top(10); - builder.steps().direction(Direction.OUT).degree(-1).top(10); - builder.steps().direction(Direction.OUT).degree(-1).top(10); - builder.alpha(0.9).capacity(-1); - NeighborRankAPI.RankRequest request = builder.build(); - - List ranks = neighborRankAPI.post(request); - Assert.assertEquals(4, ranks.size()); - Assert.assertEquals(ImmutableMap.of("O", 1.0D), ranks.get(0)); - - Assert.assertEquals(ImmutableMap.of("B", 0.45075000000000004D, - "A", 0.3D, - "C", 0.3D), - ranks.get(1)); - Assert.assertEquals(ImmutableMap.builder() - .put("G", 0.17550000000000002D) - .put("H", 0.17550000000000002D) - .put("E", 0.135D) - .put("F", 0.135D) - .put("I", 0.135D) - .put("J", 0.135D) - .build(), - ranks.get(2)); - Assert.assertEquals(ImmutableMap.of("M", 0.15795D, - "K", 0.12150000000000001D, - "L", 0.12150000000000001D), - ranks.get(3)); - } - - @Test - public void testNeighborRankWithTop() { - initNeighborRankGraph(); - - NeighborRankAPI.RankRequest.Builder builder; - builder = new NeighborRankAPI.RankRequest.Builder(); - builder.source("O"); - builder.steps().direction(Direction.OUT).degree(-1).top(2); - builder.steps().direction(Direction.OUT).degree(-1).top(3); - builder.steps().direction(Direction.OUT).degree(-1).top(2); - builder.alpha(0.9).capacity(-1); - NeighborRankAPI.RankRequest request = builder.build(); - - List ranks = neighborRankAPI.post(request); - Assert.assertEquals(4, ranks.size()); - Assert.assertEquals(ImmutableMap.of("O", 1.0D), ranks.get(0)); - - Assert.assertEquals(ImmutableMap.of("B", 0.45075000000000004D, - "A", 0.3D), - ranks.get(1)); - Assert.assertEquals(ImmutableMap.of("G", 0.17550000000000002D, - "H", 0.17550000000000002D, - "E", 0.135D), - ranks.get(2)); - Assert.assertEquals(ImmutableMap.of("M", 0.15795D, - "K", 0.12150000000000001D), - ranks.get(3)); - } - - @Test - public void testPersonalRank() { - initPersonalRankGraph(); - - PersonalRankAPI.RankRequest.Builder builder; - builder = new PersonalRankAPI.RankRequest.Builder(); - builder.source("A").label("like").alpha(0.9).maxDepth(50).build(); - PersonalRankAPI.RankRequest request = builder.build(); - - Map ranks = personalRankAPI.post(request); - Assert.assertEquals(ImmutableMap.builder() - .put("A", 0.22378692172243492D) - .put("B", 0.2065750574989044D) - .put("c", 0.18972188606657317) - .put("a", 0.1460239032907022) - .put("C", 0.09839507219265439) - .put("d", 0.08959757100230095) - .put("b", 0.04589958822642998) - .build(), ranks); - } - @Test public void testVertices() { Object markoId = getVertexId("person", "name", "marko"); @@ -1148,167 +777,4 @@ public void testScanEdgeWithSplitSizeLt1MB() { edgesAPI.shards(1 * 1024 * 1024 - 1); }); } - - - private static void initEdgesWithWeights() { - SchemaManager schema = schema(); - schema.edgeLabel("knows1") - .sourceLabel("person") - .targetLabel("person") - .properties("date", "weight") - .nullableKeys("weight") - .ifNotExist() - .create(); - - schema.edgeLabel("created1") - .sourceLabel("person") - .targetLabel("software") - .properties("date", "weight") - .nullableKeys("weight") - .ifNotExist() - .create(); - - Vertex marko = getVertex("person", "name", "marko"); - Vertex vadas = getVertex("person", "name", "vadas"); - Vertex lop = getVertex("software", "name", "lop"); - Vertex josh = getVertex("person", "name", "josh"); - Vertex ripple = getVertex("software", "name", "ripple"); - Vertex peter = getVertex("person", "name", "peter"); - - marko.addEdge("knows1", vadas, "date", "20160110", "weight", 0.5); - marko.addEdge("knows1", josh, "date", "20130220", "weight", 1.0); - marko.addEdge("created1", lop, "date", "20171210", "weight", 0.4); - josh.addEdge("created1", lop, "date", "20091111", "weight", 0.4); - josh.addEdge("created1", ripple, "date", "20171210", "weight", 1.0); - peter.addEdge("created1", lop, "date", "20170324", "weight", 0.2); - } - - private static void removeEdgesWithWeights() { - List elTaskIds = new ArrayList<>(); - EdgeLabel knows1 = schema().getEdgeLabel("knows1"); - EdgeLabel created1 = schema().getEdgeLabel("created1"); - ImmutableList.of(knows1, created1).forEach(edgeLabel -> { - elTaskIds.add(edgeLabelAPI.delete(edgeLabel.name())); - }); - elTaskIds.forEach(BaseApiTest::waitUntilTaskCompleted); - } - - private static void initNeighborRankGraph() { - GraphManager graph = graph(); - SchemaManager schema = schema(); - - schema.vertexLabel("m_person") - .properties("name") - .useCustomizeStringId() - .ifNotExist() - .create(); - - schema.vertexLabel("movie") - .properties("name") - .useCustomizeStringId() - .ifNotExist() - .create(); - - schema.edgeLabel("follow") - .sourceLabel("m_person") - .targetLabel("m_person") - .ifNotExist() - .create(); - - schema.edgeLabel("like") - .sourceLabel("m_person") - .targetLabel("movie") - .ifNotExist() - .create(); - - schema.edgeLabel("directedBy") - .sourceLabel("movie") - .targetLabel("m_person") - .ifNotExist() - .create(); - - Vertex O = graph.addVertex(T.label, "m_person", T.id, "O", "name", "O"); - - Vertex A = graph.addVertex(T.label, "m_person", T.id, "A", "name", "A"); - Vertex B = graph.addVertex(T.label, "m_person", T.id, "B", "name", "B"); - Vertex C = graph.addVertex(T.label, "m_person", T.id, "C", "name", "C"); - Vertex D = graph.addVertex(T.label, "m_person", T.id, "D", "name", "D"); - - Vertex E = graph.addVertex(T.label, "movie", T.id, "E", "name", "E"); - Vertex F = graph.addVertex(T.label, "movie", T.id, "F", "name", "F"); - Vertex G = graph.addVertex(T.label, "movie", T.id, "G", "name", "G"); - Vertex H = graph.addVertex(T.label, "movie", T.id, "H", "name", "H"); - Vertex I = graph.addVertex(T.label, "movie", T.id, "I", "name", "I"); - Vertex J = graph.addVertex(T.label, "movie", T.id, "J", "name", "J"); - - Vertex K = graph.addVertex(T.label, "m_person", T.id, "K", "name", "K"); - Vertex L = graph.addVertex(T.label, "m_person", T.id, "L", "name", "L"); - Vertex M = graph.addVertex(T.label, "m_person", T.id, "M", "name", "M"); - - O.addEdge("follow", A); - O.addEdge("follow", B); - O.addEdge("follow", C); - D.addEdge("follow", O); - - A.addEdge("follow", B); - A.addEdge("like", E); - A.addEdge("like", F); - - B.addEdge("like", G); - B.addEdge("like", H); - - C.addEdge("like", I); - C.addEdge("like", J); - - E.addEdge("directedBy", K); - F.addEdge("directedBy", B); - F.addEdge("directedBy", L); - - G.addEdge("directedBy", M); - } - - private static void initPersonalRankGraph() { - GraphManager graph = graph(); - SchemaManager schema = schema(); - - schema.propertyKey("name").asText().ifNotExist().create(); - - schema.vertexLabel("person") - .properties("name") - .useCustomizeStringId() - .ifNotExist() - .create(); - - schema.vertexLabel("movie") - .properties("name") - .useCustomizeStringId() - .ifNotExist() - .create(); - - schema.edgeLabel("like") - .sourceLabel("person") - .targetLabel("movie") - .ifNotExist() - .create(); - - Vertex A = graph.addVertex(T.label, "person", T.id, "A", "name", "A"); - Vertex B = graph.addVertex(T.label, "person", T.id, "B", "name", "B"); - Vertex C = graph.addVertex(T.label, "person", T.id, "C", "name", "C"); - - Vertex a = graph.addVertex(T.label, "movie", T.id, "a", "name", "a"); - Vertex b = graph.addVertex(T.label, "movie", T.id, "b", "name", "b"); - Vertex c = graph.addVertex(T.label, "movie", T.id, "c", "name", "c"); - Vertex d = graph.addVertex(T.label, "movie", T.id, "d", "name", "d"); - - A.addEdge("like", a); - A.addEdge("like", c); - - B.addEdge("like", a); - B.addEdge("like", b); - B.addEdge("like", c); - B.addEdge("like", d); - - C.addEdge("like", c); - C.addEdge("like", d); - } } From da8cc0f7cf5b465e832bd045aba3576f7a681836 Mon Sep 17 00:00:00 2001 From: liningrui Date: Thu, 18 Apr 2019 13:03:30 +0800 Subject: [PATCH 4/7] add some negative tests Change-Id: Ib97214692028dda1f84077b7cc38e9f3dbd8e410 --- .../api/traverser/PersonalRankAPI.java | 4 +- .../structure/constant/Traverser.java | 3 +- .../com/baidu/hugegraph/api/ApiTestSuite.java | 2 +- .../hugegraph/api/CustomizedPathsApiTest.java | 3 - .../hugegraph/api/NeighborRankApiTest.java | 77 +++++++++++++++++++ .../hugegraph/api/PersonalRankApiTest.java | 50 ++++++++++++ .../baidu/hugegraph/api/TraverserApiTest.java | 12 ++- 7 files changed, 140 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/baidu/hugegraph/api/traverser/PersonalRankAPI.java b/src/main/java/com/baidu/hugegraph/api/traverser/PersonalRankAPI.java index 3355f0f0..fe8df086 100644 --- a/src/main/java/com/baidu/hugegraph/api/traverser/PersonalRankAPI.java +++ b/src/main/java/com/baidu/hugegraph/api/traverser/PersonalRankAPI.java @@ -50,13 +50,13 @@ public static class Request { @JsonProperty("label") private String label; @JsonProperty("alpha") - private double alpha; + private double alpha = Traverser.DEFAULT_ALPHA; @JsonProperty("degree") public long degree = Traverser.DEFAULT_DEGREE; @JsonProperty("limit") private long limit = Traverser.DEFAULT_LIMIT; @JsonProperty("max_depth") - private int maxDepth; + private int maxDepth = Traverser.DEFAULT_MAX_DEPTH; @JsonProperty("with_label") private WithLabel withLabel = WithLabel.BOTH_LABEL; @JsonProperty("sorted") diff --git a/src/main/java/com/baidu/hugegraph/structure/constant/Traverser.java b/src/main/java/com/baidu/hugegraph/structure/constant/Traverser.java index 15b3bc06..3f2e2c49 100644 --- a/src/main/java/com/baidu/hugegraph/structure/constant/Traverser.java +++ b/src/main/java/com/baidu/hugegraph/structure/constant/Traverser.java @@ -31,5 +31,6 @@ public class Traverser { public static final double DEFAULT_WEIGHT = 0.0D; public static final long DEFAULT_PAGE_LIMIT = 100_000L; public static final double DEFAULT_ALPHA = 0.9; - public static final int DEFAULT_MAX_TOP = 100_000; + public static final int DEFAULT_MAX_TOP = 1000; + public static final int DEFAULT_MAX_DEPTH = 50; } diff --git a/src/test/java/com/baidu/hugegraph/api/ApiTestSuite.java b/src/test/java/com/baidu/hugegraph/api/ApiTestSuite.java index 2016184d..69e33e2f 100644 --- a/src/test/java/com/baidu/hugegraph/api/ApiTestSuite.java +++ b/src/test/java/com/baidu/hugegraph/api/ApiTestSuite.java @@ -38,7 +38,7 @@ TraverserApiTest.class, CustomizedPathsApiTest.class, NeighborRankApiTest.class, - PersonalRankApiTest.class, + PersonalRankApiTest.class }) public class ApiTestSuite { } diff --git a/src/test/java/com/baidu/hugegraph/api/CustomizedPathsApiTest.java b/src/test/java/com/baidu/hugegraph/api/CustomizedPathsApiTest.java index 1a7f38fa..95f38007 100644 --- a/src/test/java/com/baidu/hugegraph/api/CustomizedPathsApiTest.java +++ b/src/test/java/com/baidu/hugegraph/api/CustomizedPathsApiTest.java @@ -46,10 +46,7 @@ public class CustomizedPathsApiTest extends BaseApiTest { public static void prepareSchemaAndGraph() { BaseApiTest.initPropertyKey(); BaseApiTest.initVertexLabel(); - BaseApiTest.initEdgeLabel(); - BaseApiTest.initIndexLabel(); BaseApiTest.initVertex(); - BaseApiTest.initEdge(); } @Before diff --git a/src/test/java/com/baidu/hugegraph/api/NeighborRankApiTest.java b/src/test/java/com/baidu/hugegraph/api/NeighborRankApiTest.java index 35719033..f586ceb9 100644 --- a/src/test/java/com/baidu/hugegraph/api/NeighborRankApiTest.java +++ b/src/test/java/com/baidu/hugegraph/api/NeighborRankApiTest.java @@ -21,6 +21,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.Map; import org.junit.After; import org.junit.Before; @@ -28,6 +29,7 @@ import org.junit.Test; import com.baidu.hugegraph.api.traverser.NeighborRankAPI; +import com.baidu.hugegraph.api.traverser.PersonalRankAPI; import com.baidu.hugegraph.api.traverser.structure.Ranks; import com.baidu.hugegraph.driver.GraphManager; import com.baidu.hugegraph.driver.SchemaManager; @@ -260,6 +262,81 @@ public void testNeighborRankWithCapacity() { }); } + @Test + public void testNeighborRankWithIsolatedVertex() { + Vertex isolate = graph().addVertex(T.label, "person", T.id, "isolate", + "name", "isolate-vertex"); + + NeighborRankAPI.Request.Builder builder; + builder = NeighborRankAPI.Request.builder(); + builder.source("isolate").alpha(0.9); + builder.steps().direction(Direction.BOTH); + NeighborRankAPI.Request request = builder.build(); + + List ranks = neighborRankAPI.post(request); + Assert.assertEquals(2, ranks.size()); + Assert.assertEquals(ImmutableMap.of("isolate", 1.0D), ranks.get(0)); + Assert.assertEquals(ImmutableMap.of(), ranks.get(1)); + + graph().removeVertex(isolate.id()); + } + + @Test + public void testNeighborRankWithInvalidParams() { + // Invalid source + Assert.assertThrows(IllegalArgumentException.class, () -> { + NeighborRankAPI.Request.Builder builder; + builder = NeighborRankAPI.Request.builder(); + builder.source(null); + }); + + // Invalid degree + Assert.assertThrows(IllegalArgumentException.class, () -> { + NeighborRankAPI.Request.Builder builder; + builder = NeighborRankAPI.Request.builder(); + builder.steps().degree(-2); + }); + + // Invalid top + Assert.assertThrows(IllegalArgumentException.class, () -> { + NeighborRankAPI.Request.Builder builder; + builder = NeighborRankAPI.Request.builder(); + builder.steps().top(0); + }); + Assert.assertThrows(IllegalArgumentException.class, () -> { + NeighborRankAPI.Request.Builder builder; + builder = NeighborRankAPI.Request.builder(); + builder.steps().top(1001); + }); + + // Invalid alpha + Assert.assertThrows(IllegalArgumentException.class, () -> { + NeighborRankAPI.Request.Builder builder; + builder = NeighborRankAPI.Request.builder(); + builder.alpha(0.0); + }); + Assert.assertThrows(IllegalArgumentException.class, () -> { + NeighborRankAPI.Request.Builder builder; + builder = NeighborRankAPI.Request.builder(); + builder.alpha(1.1); + }); + + // Invalid capacity + Assert.assertThrows(IllegalArgumentException.class, () -> { + NeighborRankAPI.Request.Builder builder; + builder = NeighborRankAPI.Request.builder(); + builder.capacity(-2); + }); + + // Without steps + Assert.assertThrows(IllegalArgumentException.class, () -> { + NeighborRankAPI.Request.Builder builder; + builder = NeighborRankAPI.Request.builder(); + builder.source("A"); + builder.build(); + }); + } + private static void initNeighborRankGraph() { GraphManager graph = graph(); SchemaManager schema = schema(); diff --git a/src/test/java/com/baidu/hugegraph/api/PersonalRankApiTest.java b/src/test/java/com/baidu/hugegraph/api/PersonalRankApiTest.java index 290e3419..c9828dac 100644 --- a/src/test/java/com/baidu/hugegraph/api/PersonalRankApiTest.java +++ b/src/test/java/com/baidu/hugegraph/api/PersonalRankApiTest.java @@ -198,6 +198,56 @@ public void testPersonalRankWithIsolatedVertex() { graph().removeVertex(isolate.id()); } + @Test + public void testPersonalRankWithInvalidParams() { + // Invalid source + Assert.assertThrows(IllegalArgumentException.class, () -> { + PersonalRankAPI.Request.Builder builder; + builder = PersonalRankAPI.Request.builder(); + builder.source(null); + }); + + // Invalid label + Assert.assertThrows(IllegalArgumentException.class, () -> { + PersonalRankAPI.Request.Builder builder; + builder = PersonalRankAPI.Request.builder(); + builder.label(null); + }); + + // Invalid alpha + Assert.assertThrows(IllegalArgumentException.class, () -> { + PersonalRankAPI.Request.Builder builder; + builder = PersonalRankAPI.Request.builder(); + builder.alpha(0.0); + }); + Assert.assertThrows(IllegalArgumentException.class, () -> { + PersonalRankAPI.Request.Builder builder; + builder = PersonalRankAPI.Request.builder(); + builder.alpha(1.1); + }); + + // Invalid degree + Assert.assertThrows(IllegalArgumentException.class, () -> { + PersonalRankAPI.Request.Builder builder; + builder = PersonalRankAPI.Request.builder(); + builder.degree(-2); + }); + + // Invalid limit + Assert.assertThrows(IllegalArgumentException.class, () -> { + PersonalRankAPI.Request.Builder builder; + builder = PersonalRankAPI.Request.builder(); + builder.limit(-2); + }); + + // Invalid maxDepth + Assert.assertThrows(IllegalArgumentException.class, () -> { + PersonalRankAPI.Request.Builder builder; + builder = PersonalRankAPI.Request.builder(); + builder.maxDepth(0); + }); + } + private static void initPersonalRankGraph() { GraphManager graph = graph(); SchemaManager schema = schema(); diff --git a/src/test/java/com/baidu/hugegraph/api/TraverserApiTest.java b/src/test/java/com/baidu/hugegraph/api/TraverserApiTest.java index 0babef18..4d0d78cf 100644 --- a/src/test/java/com/baidu/hugegraph/api/TraverserApiTest.java +++ b/src/test/java/com/baidu/hugegraph/api/TraverserApiTest.java @@ -84,12 +84,16 @@ public void testShortestPath() { @Test public void testShortestPathWithCapacity() { Object markoId = getVertexId("person", "name", "marko"); + Object joshId = getVertexId("person", "name", "josh"); Object rippleId = getVertexId("software", "name", "ripple"); - Assert.assertThrows(ServerException.class, () -> { - shortestPathAPI.get(markoId, rippleId, Direction.BOTH, - null, 3, 1L, 0L, 2L); - }); + // NOTE: Don't throw exception after server fix degree limit lost + Path path = shortestPathAPI.get(markoId, rippleId, Direction.BOTH, + null, 3, 1L, 0L, 2L); + Assert.assertEquals(3, path.size()); + Assert.assertEquals(markoId, path.objects().get(0)); + Assert.assertEquals(joshId, path.objects().get(1)); + Assert.assertEquals(rippleId, path.objects().get(2)); } @Test From bbae80d167c145df2a4e290abad1db73d1af93ac Mon Sep 17 00:00:00 2001 From: liningrui Date: Thu, 18 Apr 2019 15:15:20 +0800 Subject: [PATCH 5/7] Add ShortestPathApiTest Change-Id: If68f2aa410453c08e85b0f4dbb09ef519be85528 --- .../api/traverser/PersonalRankAPI.java | 20 +- .../api/traverser/TraversersAPI.java | 2 +- .../com/baidu/hugegraph/api/ApiTestSuite.java | 1 + .../hugegraph/api/PersonalRankApiTest.java | 15 +- .../hugegraph/api/ShortestPathApiTest.java | 263 ++++++++++++++++++ .../baidu/hugegraph/api/TraverserApiTest.java | 207 -------------- 6 files changed, 288 insertions(+), 220 deletions(-) create mode 100644 src/test/java/com/baidu/hugegraph/api/ShortestPathApiTest.java diff --git a/src/main/java/com/baidu/hugegraph/api/traverser/PersonalRankAPI.java b/src/main/java/com/baidu/hugegraph/api/traverser/PersonalRankAPI.java index fe8df086..5309ba98 100644 --- a/src/main/java/com/baidu/hugegraph/api/traverser/PersonalRankAPI.java +++ b/src/main/java/com/baidu/hugegraph/api/traverser/PersonalRankAPI.java @@ -56,7 +56,7 @@ public static class Request { @JsonProperty("limit") private long limit = Traverser.DEFAULT_LIMIT; @JsonProperty("max_depth") - private int maxDepth = Traverser.DEFAULT_MAX_DEPTH; + private int maxDepth = 5; @JsonProperty("with_label") private WithLabel withLabel = WithLabel.BOTH_LABEL; @JsonProperty("sorted") @@ -121,9 +121,11 @@ public Builder limit(long limit) { } public Builder maxDepth(int maxDepth) { - TraversersAPI.checkPositive(maxDepth, - "max depth of rank request " + - "for personal rank"); + E.checkArgument(maxDepth > 0 && + maxDepth <= Traverser.DEFAULT_MAX_DEPTH, + "The max depth must be in range (0, %s], " + + "but got: %s", + Traverser.DEFAULT_MAX_DEPTH, maxDepth); this.request.maxDepth = maxDepth; return this; } @@ -147,9 +149,13 @@ public Request build() { TraversersAPI.checkAlpha(this.request.alpha); TraversersAPI.checkDegree(this.request.degree); TraversersAPI.checkLimit(this.request.limit); - TraversersAPI.checkPositive(this.request.maxDepth, - "max depth of rank request " + - "for personal rank"); + E.checkArgument(this.request.maxDepth > 0 && + this.request.maxDepth <= + Traverser.DEFAULT_MAX_DEPTH, + "The max depth must be in range (0, %s], " + + "but got: %s", + Traverser.DEFAULT_MAX_DEPTH, + this.request.maxDepth); return this.request; } } diff --git a/src/main/java/com/baidu/hugegraph/api/traverser/TraversersAPI.java b/src/main/java/com/baidu/hugegraph/api/traverser/TraversersAPI.java index b6f4cc25..e4258c68 100644 --- a/src/main/java/com/baidu/hugegraph/api/traverser/TraversersAPI.java +++ b/src/main/java/com/baidu/hugegraph/api/traverser/TraversersAPI.java @@ -56,7 +56,7 @@ public static void checkLimit(long limit) { public static void checkAlpha(double alpha) { E.checkArgument(alpha > 0 && alpha <= 1.0, - "The alpha of rank request must belong (0, 1], " + + "The alpha of rank request must be in range (0, 1], " + "but got '%s'", alpha); } } diff --git a/src/test/java/com/baidu/hugegraph/api/ApiTestSuite.java b/src/test/java/com/baidu/hugegraph/api/ApiTestSuite.java index 69e33e2f..49eefff2 100644 --- a/src/test/java/com/baidu/hugegraph/api/ApiTestSuite.java +++ b/src/test/java/com/baidu/hugegraph/api/ApiTestSuite.java @@ -36,6 +36,7 @@ JobApiTest.class, RestoreApiTest.class, TraverserApiTest.class, + ShortestPathApiTest.class, CustomizedPathsApiTest.class, NeighborRankApiTest.class, PersonalRankApiTest.class diff --git a/src/test/java/com/baidu/hugegraph/api/PersonalRankApiTest.java b/src/test/java/com/baidu/hugegraph/api/PersonalRankApiTest.java index c9828dac..32a90812 100644 --- a/src/test/java/com/baidu/hugegraph/api/PersonalRankApiTest.java +++ b/src/test/java/com/baidu/hugegraph/api/PersonalRankApiTest.java @@ -156,14 +156,14 @@ public void testPersonalRankWithLimit() { public void testPersonalRankWithMaxDepth() { PersonalRankAPI.Request.Builder builder; builder = PersonalRankAPI.Request.builder(); - builder.source("A").label("like").alpha(0.9).maxDepth(100); + builder.source("A").label("like").alpha(0.9).maxDepth(20); PersonalRankAPI.Request request = builder.build(); Map ranks = personalRankAPI.post(request); - Assert.assertEquals(ImmutableMap.of("B", 0.2053607173863809D, - "C", 0.09778790213639266D, - "d", 0.09020474105856267D, - "b", 0.04620317325456084D), + Assert.assertEquals(ImmutableMap.of("B", 0.23414889646372697D, + "C", 0.11218194186115384D, + "d", 0.07581065434649958D, + "b", 0.03900612828909826D), ranks); } @@ -246,6 +246,11 @@ public void testPersonalRankWithInvalidParams() { builder = PersonalRankAPI.Request.builder(); builder.maxDepth(0); }); + Assert.assertThrows(IllegalArgumentException.class, () -> { + PersonalRankAPI.Request.Builder builder; + builder = PersonalRankAPI.Request.builder(); + builder.maxDepth(51); + }); } private static void initPersonalRankGraph() { diff --git a/src/test/java/com/baidu/hugegraph/api/ShortestPathApiTest.java b/src/test/java/com/baidu/hugegraph/api/ShortestPathApiTest.java new file mode 100644 index 00000000..b98fda5a --- /dev/null +++ b/src/test/java/com/baidu/hugegraph/api/ShortestPathApiTest.java @@ -0,0 +1,263 @@ +/* + * Copyright 2017 HugeGraph Authors + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with this + * work for additional information regarding copyright ownership. The ASF + * licenses this file to You under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +package com.baidu.hugegraph.api; + +import java.util.List; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import com.baidu.hugegraph.exception.ServerException; +import com.baidu.hugegraph.structure.constant.Direction; +import com.baidu.hugegraph.structure.constant.T; +import com.baidu.hugegraph.structure.graph.Path; +import com.baidu.hugegraph.structure.graph.Vertex; +import com.baidu.hugegraph.testutil.Assert; +import com.google.common.collect.ImmutableList; + +public class ShortestPathApiTest extends BaseApiTest { + + @Before + public void setup() { + initShortestPathGraph(); + } + + @After + public void teardown() { + clearShortestPathGraph(); + } + + @Test + public void testShortestPath() { + Path path = shortestPathAPI.get(1, 6, Direction.BOTH, + null, 6, -1L, 0L, -1L); + Assert.assertEquals(4, path.size()); + Assert.assertEquals(ImmutableList.of(1, 10, 11, 6), path.objects()); + } + + @Test + public void testShortestPathWithLabel() { + Path path = shortestPathAPI.get(1, 6, Direction.BOTH, + "link", 6, -1L, 0L, -1L); + Assert.assertEquals(4, path.size()); + Assert.assertEquals(ImmutableList.of(1, 10, 11, 6), path.objects()); + } + + @Test + public void testShortestPathWithDegree() { + Path path = shortestPathAPI.get(1, 6, Direction.BOTH, + null, 6, 1L, 0L, -1L); + Assert.assertEquals(6, path.size()); + Assert.assertEquals(ImmutableList.of(1, 2, 3, 4, 5, 6), path.objects()); + } + + @Test + public void testShortestPathWithCapacity() { + Path path = shortestPathAPI.get(14, 6, Direction.BOTH, + null, 6, 5L, 0L, 19L); + Assert.assertEquals(5, path.size()); + Assert.assertEquals(ImmutableList.of(14, 7, 8, 9, 6), path.objects()); + + Assert.assertThrows(ServerException.class, () -> { + shortestPathAPI.get(14, 6, Direction.BOTH, null, 6, 1L, 0L, 2L); + }); + } + + @Test + public void testShortestPathWithMaxDepth() { + Path path = shortestPathAPI.get(14, 6, Direction.BOTH, + null, 4, 5L, 0L, 19L); + Assert.assertEquals(5, path.size()); + Assert.assertEquals(ImmutableList.of(14, 7, 8, 9, 6), path.objects()); + + path = shortestPathAPI.get(14, 6, Direction.BOTH, + null, 3, 5L, 0L, 19L); + Assert.assertEquals(0, path.size()); + } + + @Test + public void testShortestPathWithSkipDegree() { + // Path length 5 with min degree 3(v1 degree is 3) + List path1 = ImmutableList.of(1, 2, 3, 4, 5, 6); + // Path length 4 with middle degree 4(v7 degree is 4) + List path2 = ImmutableList.of(1, 7, 8, 9, 6); + // Path length 3 with max degree 5(v10 degree is 5) + List path3 = ImmutableList.of(1, 10, 11, 6); + + // (skipped degree == degree) > max degree + Path path = shortestPathAPI.get(1, 6, Direction.OUT, + null, 5, 6L, 6L, -1L); + Assert.assertEquals(4, path.size()); + Assert.assertEquals(path3, path.objects()); + + // (skipped degree == degree) == max degree + path = shortestPathAPI.get(1, 6, Direction.OUT, + null, 5, 5L, 5L, -1L); + Assert.assertEquals(5, path.size()); + Assert.assertEquals(path2, path.objects()); + + // min degree < (skipped degree == degree) == middle degree < max degree + path = shortestPathAPI.get(1, 6, Direction.OUT, + null, 5, 4L, 4L, -1L); + Assert.assertEquals(6, path.size()); + Assert.assertEquals(path1, path.objects()); + + // (skipped degree == degree) <= min degree + path = shortestPathAPI.get(1, 6, Direction.OUT, + null, 5, 3L, 3L, -1L); + Assert.assertEquals(0, path.size()); + + // Skipped degree > max degree, degree <= min degree + path = shortestPathAPI.get(1, 6, Direction.OUT, + null, 5, 3L, 6L, -1L); + Assert.assertTrue(path.size() == 4 || + path.size() == 5 || + path.size() == 6); + List> paths = ImmutableList.of(path1, path2, path3); + Assert.assertTrue(paths.contains(path.objects())); + + // Skipped degree > max degree, min degree < degree < max degree + path = shortestPathAPI.get(1, 6, Direction.OUT, + null, 5, 4L, 6L, -1L); + Assert.assertTrue(path.size() == 4 || path.size() == 5); + Assert.assertTrue(path2.equals(path.objects()) || + path3.equals(path.objects())); + + // Skipped degree > max degree, degree >= max degree + path = shortestPathAPI.get(1, 6, Direction.OUT, + null, 5, 5L, 6L, -1L); + Assert.assertEquals(4, path.size()); + Assert.assertEquals(path3, path.objects()); + } + + @Test + public void testShortestPathWithIllegalArgs() { + // The max depth shouldn't be 0 or negative + Assert.assertThrows(IllegalArgumentException.class, () -> { + shortestPathAPI.get("a", "b", Direction.BOTH, + null, -1, 1L, 0L, 2L); + }); + + Assert.assertThrows(IllegalArgumentException.class, () -> { + shortestPathAPI.get("a", "b", Direction.BOTH, + null, 0, 1L, 0L, 2L); + }); + + // The degree shouldn't be 0 or negative but NO_LIMIT(-1) + Assert.assertThrows(IllegalArgumentException.class, () -> { + shortestPathAPI.get("a", "b", Direction.BOTH, + null, 5, 0L, 0L, 2L); + }); + + Assert.assertThrows(IllegalArgumentException.class, () -> { + shortestPathAPI.get("a", "b", Direction.BOTH, + null, 5, -3L, 0L, 2L); + }); + + // The skipped degree shouldn't be negative + Assert.assertThrows(IllegalArgumentException.class, () -> { + shortestPathAPI.get("a", "b", Direction.BOTH, + null, 5, 1L, -1L, 2L); + }); + + // The skipped degree shouldn't be >= capacity + Assert.assertThrows(IllegalArgumentException.class, () -> { + shortestPathAPI.get("a", "b", Direction.BOTH, + null, 5, 1L, 2L, 2L); + }); + + // The skipped degree shouldn't be < degree + Assert.assertThrows(IllegalArgumentException.class, () -> { + shortestPathAPI.get("a", "b", Direction.BOTH, + null, 5, 3L, 2L, 10L); + }); + + Assert.assertThrows(IllegalArgumentException.class, () -> { + shortestPathAPI.get("a", "b", Direction.BOTH, + null, 5, -1L, 2L, 10L); + }); + } + + private static void initShortestPathGraph() { + schema().vertexLabel("node") + .useCustomizeNumberId() + .ifNotExist() + .create(); + + schema().edgeLabel("link") + .sourceLabel("node").targetLabel("node") + .ifNotExist() + .create(); + + Vertex v1 = graph().addVertex(T.label, "node", T.id, 1); + Vertex v2 = graph().addVertex(T.label, "node", T.id, 2); + Vertex v3 = graph().addVertex(T.label, "node", T.id, 3); + Vertex v4 = graph().addVertex(T.label, "node", T.id, 4); + Vertex v5 = graph().addVertex(T.label, "node", T.id, 5); + Vertex v6 = graph().addVertex(T.label, "node", T.id, 6); + Vertex v7 = graph().addVertex(T.label, "node", T.id, 7); + Vertex v8 = graph().addVertex(T.label, "node", T.id, 8); + Vertex v9 = graph().addVertex(T.label, "node", T.id, 9); + Vertex v10 = graph().addVertex(T.label, "node", T.id, 10); + Vertex v11 = graph().addVertex(T.label, "node", T.id, 11); + Vertex v12 = graph().addVertex(T.label, "node", T.id, 12); + Vertex v13 = graph().addVertex(T.label, "node", T.id, 13); + Vertex v14 = graph().addVertex(T.label, "node", T.id, 14); + Vertex v15 = graph().addVertex(T.label, "node", T.id, 15); + Vertex v16 = graph().addVertex(T.label, "node", T.id, 16); + Vertex v17 = graph().addVertex(T.label, "node", T.id, 17); + Vertex v18 = graph().addVertex(T.label, "node", T.id, 18); + + // Path length 5 + v1.addEdge("link", v2); + v2.addEdge("link", v3); + v3.addEdge("link", v4); + v4.addEdge("link", v5); + v5.addEdge("link", v6); + + // Path length 4 + v1.addEdge("link", v7); + v7.addEdge("link", v8); + v8.addEdge("link", v9); + v9.addEdge("link", v6); + + // Path length 3 + v1.addEdge("link", v10); + v10.addEdge("link", v11); + v11.addEdge("link", v6); + + // Add other 3 neighbor for v7 + v7.addEdge("link", v12); + v7.addEdge("link", v13); + v7.addEdge("link", v14); + + // Add other 4 neighbor for v10 + v10.addEdge("link", v15); + v10.addEdge("link", v16); + v10.addEdge("link", v17); + v10.addEdge("link", v18); + } + + private static void clearShortestPathGraph() { + waitUntilTaskCompleted(edgeLabelAPI.delete("link")); + waitUntilTaskCompleted(vertexLabelAPI.delete("node")); + } +} diff --git a/src/test/java/com/baidu/hugegraph/api/TraverserApiTest.java b/src/test/java/com/baidu/hugegraph/api/TraverserApiTest.java index 4d0d78cf..f1b3df31 100644 --- a/src/test/java/com/baidu/hugegraph/api/TraverserApiTest.java +++ b/src/test/java/com/baidu/hugegraph/api/TraverserApiTest.java @@ -21,7 +21,6 @@ import static com.baidu.hugegraph.structure.constant.Traverser.DEFAULT_PAGE_LIMIT; -import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -31,29 +30,19 @@ import org.junit.BeforeClass; import org.junit.Test; -import com.baidu.hugegraph.api.traverser.NeighborRankAPI; -import com.baidu.hugegraph.api.traverser.PersonalRankAPI; import com.baidu.hugegraph.api.traverser.structure.CrosspointsRequest; import com.baidu.hugegraph.api.traverser.structure.CustomizedCrosspoints; -import com.baidu.hugegraph.api.traverser.structure.CustomizedPaths; -import com.baidu.hugegraph.api.traverser.structure.PathsRequest; -import com.baidu.hugegraph.api.traverser.structure.Ranks; -import com.baidu.hugegraph.driver.GraphManager; -import com.baidu.hugegraph.driver.SchemaManager; import com.baidu.hugegraph.exception.ServerException; import com.baidu.hugegraph.structure.constant.Direction; -import com.baidu.hugegraph.structure.constant.T; import com.baidu.hugegraph.structure.graph.Edge; import com.baidu.hugegraph.structure.graph.Edges; import com.baidu.hugegraph.structure.graph.Path; import com.baidu.hugegraph.structure.graph.Shard; import com.baidu.hugegraph.structure.graph.Vertex; import com.baidu.hugegraph.structure.graph.Vertices; -import com.baidu.hugegraph.structure.schema.EdgeLabel; import com.baidu.hugegraph.testutil.Assert; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; public class TraverserApiTest extends BaseApiTest { @@ -67,202 +56,6 @@ public static void prepareSchemaAndGraph() { BaseApiTest.initEdge(); } - @Test - public void testShortestPath() { - Object markoId = getVertexId("person", "name", "marko"); - Object joshId = getVertexId("person", "name", "josh"); - Object rippleId = getVertexId("software", "name", "ripple"); - - Path path = shortestPathAPI.get(markoId, rippleId, Direction.BOTH, - null, 3, -1L, 0L, -1L); - Assert.assertEquals(3, path.size()); - Assert.assertEquals(markoId, path.objects().get(0)); - Assert.assertEquals(joshId, path.objects().get(1)); - Assert.assertEquals(rippleId, path.objects().get(2)); - } - - @Test - public void testShortestPathWithCapacity() { - Object markoId = getVertexId("person", "name", "marko"); - Object joshId = getVertexId("person", "name", "josh"); - Object rippleId = getVertexId("software", "name", "ripple"); - - // NOTE: Don't throw exception after server fix degree limit lost - Path path = shortestPathAPI.get(markoId, rippleId, Direction.BOTH, - null, 3, 1L, 0L, 2L); - Assert.assertEquals(3, path.size()); - Assert.assertEquals(markoId, path.objects().get(0)); - Assert.assertEquals(joshId, path.objects().get(1)); - Assert.assertEquals(rippleId, path.objects().get(2)); - } - - @Test - public void testShortestPathWithSkipDegree() { - schema().vertexLabel("node") - .useCustomizeNumberId() - .ifNotExist() - .create(); - - schema().edgeLabel("link") - .sourceLabel("node").targetLabel("node") - .ifNotExist() - .create(); - - Vertex v1 = graph().addVertex(T.label, "node", T.id, 1); - Vertex v2 = graph().addVertex(T.label, "node", T.id, 2); - Vertex v3 = graph().addVertex(T.label, "node", T.id, 3); - Vertex v4 = graph().addVertex(T.label, "node", T.id, 4); - Vertex v5 = graph().addVertex(T.label, "node", T.id, 5); - Vertex v6 = graph().addVertex(T.label, "node", T.id, 6); - Vertex v7 = graph().addVertex(T.label, "node", T.id, 7); - Vertex v8 = graph().addVertex(T.label, "node", T.id, 8); - Vertex v9 = graph().addVertex(T.label, "node", T.id, 9); - Vertex v10 = graph().addVertex(T.label, "node", T.id, 10); - Vertex v11 = graph().addVertex(T.label, "node", T.id, 11); - Vertex v12 = graph().addVertex(T.label, "node", T.id, 12); - Vertex v13 = graph().addVertex(T.label, "node", T.id, 13); - Vertex v14 = graph().addVertex(T.label, "node", T.id, 14); - Vertex v15 = graph().addVertex(T.label, "node", T.id, 15); - Vertex v16 = graph().addVertex(T.label, "node", T.id, 16); - Vertex v17 = graph().addVertex(T.label, "node", T.id, 17); - Vertex v18 = graph().addVertex(T.label, "node", T.id, 18); - - // Path length 5 - v1.addEdge("link", v2); - v2.addEdge("link", v3); - v3.addEdge("link", v4); - v4.addEdge("link", v5); - v5.addEdge("link", v6); - - // Path length 4 - v1.addEdge("link", v7); - v7.addEdge("link", v8); - v8.addEdge("link", v9); - v9.addEdge("link", v6); - - // Path length 3 - v1.addEdge("link", v10); - v10.addEdge("link", v11); - v11.addEdge("link", v6); - - // Add other 3 neighbor for v7 - v7.addEdge("link", v12); - v7.addEdge("link", v13); - v7.addEdge("link", v14); - - // Add other 4 neighbor for v10 - v10.addEdge("link", v15); - v10.addEdge("link", v16); - v10.addEdge("link", v17); - v10.addEdge("link", v18); - - // Path length 5 with min degree 3(v1 degree is 3) - List path1 = ImmutableList.of(v1.id(), v2.id(), v3.id(), - v4.id(), v5.id(), v6.id()); - // Path length 4 with middle degree 4(v7 degree is 4) - List path2 = ImmutableList.of(v1.id(), v7.id(), v8.id(), - v9.id(), v6.id()); - // Path length 3 with max degree 5(v10 degree is 5) - List path3 = ImmutableList.of(v1.id(), v10.id(), - v11.id(), v6.id()); - - // (skipped degree == degree) > max degree - Path path = shortestPathAPI.get(v1.id(), v6.id(), Direction.OUT, - null, 5, 6L, 6L, -1L); - Assert.assertEquals(4, path.size()); - Assert.assertEquals(path3, path.objects()); - - // (skipped degree == degree) == max degree - path = shortestPathAPI.get(v1.id(), v6.id(), Direction.OUT, - null, 5, 5L, 5L, -1L); - Assert.assertEquals(5, path.size()); - Assert.assertEquals(path2, path.objects()); - - // min degree < (skipped degree == degree) == middle degree < max degree - path = shortestPathAPI.get(v1.id(), v6.id(), Direction.OUT, - null, 5, 4L, 4L, -1L); - Assert.assertEquals(6, path.size()); - Assert.assertEquals(path1, path.objects()); - - // (skipped degree == degree) <= min degree - path = shortestPathAPI.get(v1.id(), v6.id(), Direction.OUT, - null, 5, 3L, 3L, -1L); - Assert.assertEquals(0, path.size()); - - // Skipped degree > max degree, degree <= min degree - path = shortestPathAPI.get(v1.id(), v6.id(), Direction.OUT, - null, 5, 3L, 6L, -1L); - Assert.assertTrue(path.size() == 4 || - path.size() == 5 || - path.size() == 6); - List> paths = ImmutableList.of(path1, path2, path3); - Assert.assertTrue(paths.contains(path.objects())); - - // Skipped degree > max degree, min degree < degree < max degree - path = shortestPathAPI.get(v1.id(), v6.id(), Direction.OUT, - null, 5, 4L, 6L, -1L); - Assert.assertTrue(path.size() == 4 || path.size() == 5); - Assert.assertTrue(path2.equals(path.objects()) || - path3.equals(path.objects())); - - // Skipped degree > max degree, degree >= max degree - path = shortestPathAPI.get(v1.id(), v6.id(), Direction.OUT, - null, 5, 5L, 6L, -1L); - Assert.assertEquals(4, path.size()); - Assert.assertEquals(path3, path.objects()); - - waitUntilTaskCompleted(edgeLabelAPI.delete("link")); - waitUntilTaskCompleted(vertexLabelAPI.delete("node")); - } - - @Test - public void testShortestPathWithIllegalArgs() { - // The max depth shouldn't be 0 or negative - Assert.assertThrows(IllegalArgumentException.class, () -> { - shortestPathAPI.get("a", "b", Direction.BOTH, - null, -1, 1L, 0L, 2L); - }); - - Assert.assertThrows(IllegalArgumentException.class, () -> { - shortestPathAPI.get("a", "b", Direction.BOTH, - null, 0, 1L, 0L, 2L); - }); - - // The degree shouldn't be 0 or negative but NO_LIMIT(-1) - Assert.assertThrows(IllegalArgumentException.class, () -> { - shortestPathAPI.get("a", "b", Direction.BOTH, - null, 5, 0L, 0L, 2L); - }); - - Assert.assertThrows(IllegalArgumentException.class, () -> { - shortestPathAPI.get("a", "b", Direction.BOTH, - null, 5, -3L, 0L, 2L); - }); - - // The skipped degree shouldn't be negative - Assert.assertThrows(IllegalArgumentException.class, () -> { - shortestPathAPI.get("a", "b", Direction.BOTH, - null, 5, 1L, -1L, 2L); - }); - - // The skipped degree shouldn't be >= capacity - Assert.assertThrows(IllegalArgumentException.class, () -> { - shortestPathAPI.get("a", "b", Direction.BOTH, - null, 5, 1L, 2L, 2L); - }); - - // The skipped degree shouldn't be < degree - Assert.assertThrows(IllegalArgumentException.class, () -> { - shortestPathAPI.get("a", "b", Direction.BOTH, - null, 5, 3L, 2L, 10L); - }); - - Assert.assertThrows(IllegalArgumentException.class, () -> { - shortestPathAPI.get("a", "b", Direction.BOTH, - null, 5, -1L, 2L, 10L); - }); - } - @Test public void testPaths() { Object markoId = getVertexId("person", "name", "marko"); From 1e86d544c5027e74b0f5551b3cc729bc0b035f9d Mon Sep 17 00:00:00 2001 From: liningrui Date: Thu, 18 Apr 2019 20:39:27 +0800 Subject: [PATCH 6/7] Use @BeforeClass and @AfterClass Change-Id: Ia42010e5845cd2a2e95e24e6c3cea04670428710 --- .../hugegraph/api/NeighborRankApiTest.java | 184 ++++++++--------- .../hugegraph/api/PersonalRankApiTest.java | 192 +++++++++--------- .../hugegraph/api/ShortestPathApiTest.java | 154 +++++++------- 3 files changed, 254 insertions(+), 276 deletions(-) diff --git a/src/test/java/com/baidu/hugegraph/api/NeighborRankApiTest.java b/src/test/java/com/baidu/hugegraph/api/NeighborRankApiTest.java index f586ceb9..69a01099 100644 --- a/src/test/java/com/baidu/hugegraph/api/NeighborRankApiTest.java +++ b/src/test/java/com/baidu/hugegraph/api/NeighborRankApiTest.java @@ -21,15 +21,12 @@ import java.util.ArrayList; import java.util.List; -import java.util.Map; -import org.junit.After; -import org.junit.Before; +import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; import com.baidu.hugegraph.api.traverser.NeighborRankAPI; -import com.baidu.hugegraph.api.traverser.PersonalRankAPI; import com.baidu.hugegraph.api.traverser.structure.Ranks; import com.baidu.hugegraph.driver.GraphManager; import com.baidu.hugegraph.driver.SchemaManager; @@ -43,18 +40,93 @@ public class NeighborRankApiTest extends BaseApiTest { @BeforeClass - public static void prepareSchemaAndGraph() { - BaseApiTest.initPropertyKey(); - } + public static void initNeighborRankGraph() { + GraphManager graph = graph(); + SchemaManager schema = schema(); + + schema.propertyKey("name").asText().ifNotExist().create(); + + schema.vertexLabel("person") + .properties("name") + .useCustomizeStringId() + .ifNotExist() + .create(); + + schema.vertexLabel("movie") + .properties("name") + .useCustomizeStringId() + .ifNotExist() + .create(); + + schema.edgeLabel("follow") + .sourceLabel("person") + .targetLabel("person") + .ifNotExist() + .create(); - @Before - public void setup() { - initNeighborRankGraph(); + schema.edgeLabel("like") + .sourceLabel("person") + .targetLabel("movie") + .ifNotExist() + .create(); + + schema.edgeLabel("directedBy") + .sourceLabel("movie") + .targetLabel("person") + .ifNotExist() + .create(); + + Vertex O = graph.addVertex(T.label, "person", T.id, "O", "name", "O"); + + Vertex A = graph.addVertex(T.label, "person", T.id, "A", "name", "A"); + Vertex B = graph.addVertex(T.label, "person", T.id, "B", "name", "B"); + Vertex C = graph.addVertex(T.label, "person", T.id, "C", "name", "C"); + Vertex D = graph.addVertex(T.label, "person", T.id, "D", "name", "D"); + + Vertex E = graph.addVertex(T.label, "movie", T.id, "E", "name", "E"); + Vertex F = graph.addVertex(T.label, "movie", T.id, "F", "name", "F"); + Vertex G = graph.addVertex(T.label, "movie", T.id, "G", "name", "G"); + Vertex H = graph.addVertex(T.label, "movie", T.id, "H", "name", "H"); + Vertex I = graph.addVertex(T.label, "movie", T.id, "I", "name", "I"); + Vertex J = graph.addVertex(T.label, "movie", T.id, "J", "name", "J"); + + Vertex K = graph.addVertex(T.label, "person", T.id, "K", "name", "K"); + Vertex L = graph.addVertex(T.label, "person", T.id, "L", "name", "L"); + Vertex M = graph.addVertex(T.label, "person", T.id, "M", "name", "M"); + + O.addEdge("follow", A); + O.addEdge("follow", B); + O.addEdge("follow", C); + D.addEdge("follow", O); + + A.addEdge("follow", B); + A.addEdge("like", E); + A.addEdge("like", F); + + B.addEdge("like", G); + B.addEdge("like", H); + + C.addEdge("like", I); + C.addEdge("like", J); + + E.addEdge("directedBy", K); + F.addEdge("directedBy", B); + F.addEdge("directedBy", L); + + G.addEdge("directedBy", M); } - @After - public void teardown() { - clearNeighborRankGraph(); + @AfterClass + public static void clearNeighborRankGraph() { + List taskIds = new ArrayList<>(); + taskIds.add(edgeLabelAPI.delete("directedBy")); + taskIds.add(edgeLabelAPI.delete("like")); + taskIds.add(edgeLabelAPI.delete("follow")); + taskIds.forEach(BaseApiTest::waitUntilTaskCompleted); + taskIds.clear(); + taskIds.add(vertexLabelAPI.delete("movie")); + taskIds.add(vertexLabelAPI.delete("person")); + taskIds.forEach(BaseApiTest::waitUntilTaskCompleted); } @Test @@ -336,90 +408,4 @@ public void testNeighborRankWithInvalidParams() { builder.build(); }); } - - private static void initNeighborRankGraph() { - GraphManager graph = graph(); - SchemaManager schema = schema(); - - schema.vertexLabel("person") - .properties("name") - .useCustomizeStringId() - .ifNotExist() - .create(); - - schema.vertexLabel("movie") - .properties("name") - .useCustomizeStringId() - .ifNotExist() - .create(); - - schema.edgeLabel("follow") - .sourceLabel("person") - .targetLabel("person") - .ifNotExist() - .create(); - - schema.edgeLabel("like") - .sourceLabel("person") - .targetLabel("movie") - .ifNotExist() - .create(); - - schema.edgeLabel("directedBy") - .sourceLabel("movie") - .targetLabel("person") - .ifNotExist() - .create(); - - Vertex O = graph.addVertex(T.label, "person", T.id, "O", "name", "O"); - - Vertex A = graph.addVertex(T.label, "person", T.id, "A", "name", "A"); - Vertex B = graph.addVertex(T.label, "person", T.id, "B", "name", "B"); - Vertex C = graph.addVertex(T.label, "person", T.id, "C", "name", "C"); - Vertex D = graph.addVertex(T.label, "person", T.id, "D", "name", "D"); - - Vertex E = graph.addVertex(T.label, "movie", T.id, "E", "name", "E"); - Vertex F = graph.addVertex(T.label, "movie", T.id, "F", "name", "F"); - Vertex G = graph.addVertex(T.label, "movie", T.id, "G", "name", "G"); - Vertex H = graph.addVertex(T.label, "movie", T.id, "H", "name", "H"); - Vertex I = graph.addVertex(T.label, "movie", T.id, "I", "name", "I"); - Vertex J = graph.addVertex(T.label, "movie", T.id, "J", "name", "J"); - - Vertex K = graph.addVertex(T.label, "person", T.id, "K", "name", "K"); - Vertex L = graph.addVertex(T.label, "person", T.id, "L", "name", "L"); - Vertex M = graph.addVertex(T.label, "person", T.id, "M", "name", "M"); - - O.addEdge("follow", A); - O.addEdge("follow", B); - O.addEdge("follow", C); - D.addEdge("follow", O); - - A.addEdge("follow", B); - A.addEdge("like", E); - A.addEdge("like", F); - - B.addEdge("like", G); - B.addEdge("like", H); - - C.addEdge("like", I); - C.addEdge("like", J); - - E.addEdge("directedBy", K); - F.addEdge("directedBy", B); - F.addEdge("directedBy", L); - - G.addEdge("directedBy", M); - } - - private static void clearNeighborRankGraph() { - List taskIds = new ArrayList<>(); - taskIds.add(edgeLabelAPI.delete("directedBy")); - taskIds.add(edgeLabelAPI.delete("like")); - taskIds.add(edgeLabelAPI.delete("follow")); - taskIds.forEach(BaseApiTest::waitUntilTaskCompleted); - taskIds.clear(); - taskIds.add(vertexLabelAPI.delete("movie")); - taskIds.add(vertexLabelAPI.delete("person")); - taskIds.forEach(BaseApiTest::waitUntilTaskCompleted); - } } diff --git a/src/test/java/com/baidu/hugegraph/api/PersonalRankApiTest.java b/src/test/java/com/baidu/hugegraph/api/PersonalRankApiTest.java index 32a90812..ad297fe0 100644 --- a/src/test/java/com/baidu/hugegraph/api/PersonalRankApiTest.java +++ b/src/test/java/com/baidu/hugegraph/api/PersonalRankApiTest.java @@ -23,8 +23,7 @@ import java.util.List; import java.util.Map; -import org.junit.After; -import org.junit.Before; +import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; @@ -39,18 +38,60 @@ public class PersonalRankApiTest extends BaseApiTest { @BeforeClass - public static void prepareSchemaAndGraph() { - BaseApiTest.initPropertyKey(); - } + public static void initPersonalRankGraph() { + GraphManager graph = graph(); + SchemaManager schema = schema(); + + schema.propertyKey("name").asText().ifNotExist().create(); + + schema.vertexLabel("person") + .properties("name") + .useCustomizeStringId() + .ifNotExist() + .create(); + + schema.vertexLabel("movie") + .properties("name") + .useCustomizeStringId() + .ifNotExist() + .create(); - @Before - public void setup() { - initPersonalRankGraph(); + schema.edgeLabel("like") + .sourceLabel("person") + .targetLabel("movie") + .ifNotExist() + .create(); + + Vertex A = graph.addVertex(T.label, "person", T.id, "A", "name", "A"); + Vertex B = graph.addVertex(T.label, "person", T.id, "B", "name", "B"); + Vertex C = graph.addVertex(T.label, "person", T.id, "C", "name", "C"); + + Vertex a = graph.addVertex(T.label, "movie", T.id, "a", "name", "a"); + Vertex b = graph.addVertex(T.label, "movie", T.id, "b", "name", "b"); + Vertex c = graph.addVertex(T.label, "movie", T.id, "c", "name", "c"); + Vertex d = graph.addVertex(T.label, "movie", T.id, "d", "name", "d"); + + A.addEdge("like", a); + A.addEdge("like", c); + + B.addEdge("like", a); + B.addEdge("like", b); + B.addEdge("like", c); + B.addEdge("like", d); + + C.addEdge("like", c); + C.addEdge("like", d); } - @After - public void teardown() { - clearPersonalRankGraph(); + @AfterClass + public static void clearPersonalRankGraph() { + List taskIds = new ArrayList<>(); + taskIds.add(edgeLabelAPI.delete("like")); + taskIds.forEach(BaseApiTest::waitUntilTaskCompleted); + taskIds.clear(); + taskIds.add(vertexLabelAPI.delete("movie")); + taskIds.add(vertexLabelAPI.delete("person")); + taskIds.forEach(BaseApiTest::waitUntilTaskCompleted); } @Test @@ -61,11 +102,13 @@ public void testPersonalRank() { PersonalRankAPI.Request request = builder.build(); Map ranks = personalRankAPI.post(request); - Assert.assertEquals(ImmutableMap.of("B", 0.2065750574989044D, - "C", 0.09839507219265439D, - "d", 0.08959757100230095D, - "b", 0.04589958822642998D), - ranks); + Map expectedRanks = ImmutableMap.of( + "B", 0.2065750574989044D, + "C", 0.09839507219265439D, + "d", 0.08959757100230095D, + "b", 0.04589958822642998D + ); + Assert.assertEquals(expectedRanks, ranks); } @Test @@ -77,9 +120,11 @@ public void testPersonalRankWithWithLabel() { PersonalRankAPI.Request request = builder.build(); Map ranks = personalRankAPI.post(request); - Assert.assertEquals(ImmutableMap.of("B", 0.2065750574989044D, - "C", 0.09839507219265439D), - ranks); + Map expectedRanks = ImmutableMap.of( + "B", 0.2065750574989044D, + "C", 0.09839507219265439D + ); + Assert.assertEquals(expectedRanks, ranks); builder = PersonalRankAPI.Request.builder(); builder.source("A").label("like").alpha(0.9).maxDepth(50) @@ -87,9 +132,11 @@ public void testPersonalRankWithWithLabel() { request = builder.build(); ranks = personalRankAPI.post(request); - Assert.assertEquals(ImmutableMap.of("d", 0.08959757100230095D, - "b", 0.04589958822642998D), - ranks); + expectedRanks = ImmutableMap.of( + "d", 0.08959757100230095D, + "b", 0.04589958822642998D + ); + Assert.assertEquals(expectedRanks, ranks); } @Test @@ -100,11 +147,13 @@ public void testPersonalRankWithOtherAlpha() { PersonalRankAPI.Request request = builder.build(); Map ranks = personalRankAPI.post(request); - Assert.assertEquals(ImmutableMap.of("B", 0.5D, - "C", 0.24999999999999956D, - "b", 0.0D, - "d", 0.0D), - ranks); + Map expectedRanks = ImmutableMap.of( + "B", 0.5D, + "C", 0.24999999999999956D, + "b", 0.0D, + "d", 0.0D + ); + Assert.assertEquals(expectedRanks, ranks); } @Test @@ -146,10 +195,12 @@ public void testPersonalRankWithLimit() { PersonalRankAPI.Request request = builder.build(); Map ranks = personalRankAPI.post(request); - Assert.assertEquals(ImmutableMap.of("B", 0.2065750574989044D, - "C", 0.09839507219265439D, - "d", 0.08959757100230095D), - ranks); + Map expectedRanks = ImmutableMap.of( + "B", 0.2065750574989044D, + "C", 0.09839507219265439D, + "d", 0.08959757100230095D + ); + Assert.assertEquals(expectedRanks, ranks); } @Test @@ -160,11 +211,13 @@ public void testPersonalRankWithMaxDepth() { PersonalRankAPI.Request request = builder.build(); Map ranks = personalRankAPI.post(request); - Assert.assertEquals(ImmutableMap.of("B", 0.23414889646372697D, - "C", 0.11218194186115384D, - "d", 0.07581065434649958D, - "b", 0.03900612828909826D), - ranks); + Map expectedRanks = ImmutableMap.of( + "B", 0.23414889646372697D, + "C", 0.11218194186115384D, + "d", 0.07581065434649958D, + "b", 0.03900612828909826D + ); + Assert.assertEquals(expectedRanks, ranks); } @Test @@ -175,11 +228,13 @@ public void testPersonalRankWithUnsorted() { PersonalRankAPI.Request request = builder.build(); Map ranks = personalRankAPI.post(request); - Assert.assertEquals(ImmutableMap.of("b", 0.04589958822642998D, - "B", 0.2065750574989044D, - "C", 0.09839507219265439D, - "d", 0.08959757100230095D), - ranks); + Map expectedRanks = ImmutableMap.of( + "b", 0.04589958822642998D, + "B", 0.2065750574989044D, + "C", 0.09839507219265439D, + "d", 0.08959757100230095D + ); + Assert.assertEquals(expectedRanks, ranks); } @Test @@ -252,59 +307,4 @@ public void testPersonalRankWithInvalidParams() { builder.maxDepth(51); }); } - - private static void initPersonalRankGraph() { - GraphManager graph = graph(); - SchemaManager schema = schema(); - - schema.propertyKey("name").asText().ifNotExist().create(); - - schema.vertexLabel("person") - .properties("name") - .useCustomizeStringId() - .ifNotExist() - .create(); - - schema.vertexLabel("movie") - .properties("name") - .useCustomizeStringId() - .ifNotExist() - .create(); - - schema.edgeLabel("like") - .sourceLabel("person") - .targetLabel("movie") - .ifNotExist() - .create(); - - Vertex A = graph.addVertex(T.label, "person", T.id, "A", "name", "A"); - Vertex B = graph.addVertex(T.label, "person", T.id, "B", "name", "B"); - Vertex C = graph.addVertex(T.label, "person", T.id, "C", "name", "C"); - - Vertex a = graph.addVertex(T.label, "movie", T.id, "a", "name", "a"); - Vertex b = graph.addVertex(T.label, "movie", T.id, "b", "name", "b"); - Vertex c = graph.addVertex(T.label, "movie", T.id, "c", "name", "c"); - Vertex d = graph.addVertex(T.label, "movie", T.id, "d", "name", "d"); - - A.addEdge("like", a); - A.addEdge("like", c); - - B.addEdge("like", a); - B.addEdge("like", b); - B.addEdge("like", c); - B.addEdge("like", d); - - C.addEdge("like", c); - C.addEdge("like", d); - } - - private void clearPersonalRankGraph() { - List taskIds = new ArrayList<>(); - taskIds.add(edgeLabelAPI.delete("like")); - taskIds.forEach(BaseApiTest::waitUntilTaskCompleted); - taskIds.clear(); - taskIds.add(vertexLabelAPI.delete("movie")); - taskIds.add(vertexLabelAPI.delete("person")); - taskIds.forEach(BaseApiTest::waitUntilTaskCompleted); - } } diff --git a/src/test/java/com/baidu/hugegraph/api/ShortestPathApiTest.java b/src/test/java/com/baidu/hugegraph/api/ShortestPathApiTest.java index b98fda5a..618d9265 100644 --- a/src/test/java/com/baidu/hugegraph/api/ShortestPathApiTest.java +++ b/src/test/java/com/baidu/hugegraph/api/ShortestPathApiTest.java @@ -21,8 +21,8 @@ import java.util.List; -import org.junit.After; -import org.junit.Before; +import org.junit.AfterClass; +import org.junit.BeforeClass; import org.junit.Test; import com.baidu.hugegraph.exception.ServerException; @@ -35,14 +35,71 @@ public class ShortestPathApiTest extends BaseApiTest { - @Before - public void setup() { - initShortestPathGraph(); + @BeforeClass + public static void initShortestPathGraph() { + schema().vertexLabel("node") + .useCustomizeNumberId() + .ifNotExist() + .create(); + + schema().edgeLabel("link") + .sourceLabel("node").targetLabel("node") + .ifNotExist() + .create(); + + Vertex v1 = graph().addVertex(T.label, "node", T.id, 1); + Vertex v2 = graph().addVertex(T.label, "node", T.id, 2); + Vertex v3 = graph().addVertex(T.label, "node", T.id, 3); + Vertex v4 = graph().addVertex(T.label, "node", T.id, 4); + Vertex v5 = graph().addVertex(T.label, "node", T.id, 5); + Vertex v6 = graph().addVertex(T.label, "node", T.id, 6); + Vertex v7 = graph().addVertex(T.label, "node", T.id, 7); + Vertex v8 = graph().addVertex(T.label, "node", T.id, 8); + Vertex v9 = graph().addVertex(T.label, "node", T.id, 9); + Vertex v10 = graph().addVertex(T.label, "node", T.id, 10); + Vertex v11 = graph().addVertex(T.label, "node", T.id, 11); + Vertex v12 = graph().addVertex(T.label, "node", T.id, 12); + Vertex v13 = graph().addVertex(T.label, "node", T.id, 13); + Vertex v14 = graph().addVertex(T.label, "node", T.id, 14); + Vertex v15 = graph().addVertex(T.label, "node", T.id, 15); + Vertex v16 = graph().addVertex(T.label, "node", T.id, 16); + Vertex v17 = graph().addVertex(T.label, "node", T.id, 17); + Vertex v18 = graph().addVertex(T.label, "node", T.id, 18); + + // Path length 5 + v1.addEdge("link", v2); + v2.addEdge("link", v3); + v3.addEdge("link", v4); + v4.addEdge("link", v5); + v5.addEdge("link", v6); + + // Path length 4 + v1.addEdge("link", v7); + v7.addEdge("link", v8); + v8.addEdge("link", v9); + v9.addEdge("link", v6); + + // Path length 3 + v1.addEdge("link", v10); + v10.addEdge("link", v11); + v11.addEdge("link", v6); + + // Add other 3 neighbor for v7 + v7.addEdge("link", v12); + v7.addEdge("link", v13); + v7.addEdge("link", v14); + + // Add other 4 neighbor for v10 + v10.addEdge("link", v15); + v10.addEdge("link", v16); + v10.addEdge("link", v17); + v10.addEdge("link", v18); } - @After - public void teardown() { - clearShortestPathGraph(); + @AfterClass + public static void clearShortestPathGraph() { + waitUntilTaskCompleted(edgeLabelAPI.delete("link")); + waitUntilTaskCompleted(vertexLabelAPI.delete("node")); } @Test @@ -153,111 +210,46 @@ public void testShortestPathWithIllegalArgs() { // The max depth shouldn't be 0 or negative Assert.assertThrows(IllegalArgumentException.class, () -> { shortestPathAPI.get("a", "b", Direction.BOTH, - null, -1, 1L, 0L, 2L); + null, -1, 1L, 0L, 2L); }); Assert.assertThrows(IllegalArgumentException.class, () -> { shortestPathAPI.get("a", "b", Direction.BOTH, - null, 0, 1L, 0L, 2L); + null, 0, 1L, 0L, 2L); }); // The degree shouldn't be 0 or negative but NO_LIMIT(-1) Assert.assertThrows(IllegalArgumentException.class, () -> { shortestPathAPI.get("a", "b", Direction.BOTH, - null, 5, 0L, 0L, 2L); + null, 5, 0L, 0L, 2L); }); Assert.assertThrows(IllegalArgumentException.class, () -> { shortestPathAPI.get("a", "b", Direction.BOTH, - null, 5, -3L, 0L, 2L); + null, 5, -3L, 0L, 2L); }); // The skipped degree shouldn't be negative Assert.assertThrows(IllegalArgumentException.class, () -> { shortestPathAPI.get("a", "b", Direction.BOTH, - null, 5, 1L, -1L, 2L); + null, 5, 1L, -1L, 2L); }); // The skipped degree shouldn't be >= capacity Assert.assertThrows(IllegalArgumentException.class, () -> { shortestPathAPI.get("a", "b", Direction.BOTH, - null, 5, 1L, 2L, 2L); + null, 5, 1L, 2L, 2L); }); // The skipped degree shouldn't be < degree Assert.assertThrows(IllegalArgumentException.class, () -> { shortestPathAPI.get("a", "b", Direction.BOTH, - null, 5, 3L, 2L, 10L); + null, 5, 3L, 2L, 10L); }); Assert.assertThrows(IllegalArgumentException.class, () -> { shortestPathAPI.get("a", "b", Direction.BOTH, - null, 5, -1L, 2L, 10L); + null, 5, -1L, 2L, 10L); }); } - - private static void initShortestPathGraph() { - schema().vertexLabel("node") - .useCustomizeNumberId() - .ifNotExist() - .create(); - - schema().edgeLabel("link") - .sourceLabel("node").targetLabel("node") - .ifNotExist() - .create(); - - Vertex v1 = graph().addVertex(T.label, "node", T.id, 1); - Vertex v2 = graph().addVertex(T.label, "node", T.id, 2); - Vertex v3 = graph().addVertex(T.label, "node", T.id, 3); - Vertex v4 = graph().addVertex(T.label, "node", T.id, 4); - Vertex v5 = graph().addVertex(T.label, "node", T.id, 5); - Vertex v6 = graph().addVertex(T.label, "node", T.id, 6); - Vertex v7 = graph().addVertex(T.label, "node", T.id, 7); - Vertex v8 = graph().addVertex(T.label, "node", T.id, 8); - Vertex v9 = graph().addVertex(T.label, "node", T.id, 9); - Vertex v10 = graph().addVertex(T.label, "node", T.id, 10); - Vertex v11 = graph().addVertex(T.label, "node", T.id, 11); - Vertex v12 = graph().addVertex(T.label, "node", T.id, 12); - Vertex v13 = graph().addVertex(T.label, "node", T.id, 13); - Vertex v14 = graph().addVertex(T.label, "node", T.id, 14); - Vertex v15 = graph().addVertex(T.label, "node", T.id, 15); - Vertex v16 = graph().addVertex(T.label, "node", T.id, 16); - Vertex v17 = graph().addVertex(T.label, "node", T.id, 17); - Vertex v18 = graph().addVertex(T.label, "node", T.id, 18); - - // Path length 5 - v1.addEdge("link", v2); - v2.addEdge("link", v3); - v3.addEdge("link", v4); - v4.addEdge("link", v5); - v5.addEdge("link", v6); - - // Path length 4 - v1.addEdge("link", v7); - v7.addEdge("link", v8); - v8.addEdge("link", v9); - v9.addEdge("link", v6); - - // Path length 3 - v1.addEdge("link", v10); - v10.addEdge("link", v11); - v11.addEdge("link", v6); - - // Add other 3 neighbor for v7 - v7.addEdge("link", v12); - v7.addEdge("link", v13); - v7.addEdge("link", v14); - - // Add other 4 neighbor for v10 - v10.addEdge("link", v15); - v10.addEdge("link", v16); - v10.addEdge("link", v17); - v10.addEdge("link", v18); - } - - private static void clearShortestPathGraph() { - waitUntilTaskCompleted(edgeLabelAPI.delete("link")); - waitUntilTaskCompleted(vertexLabelAPI.delete("node")); - } } From 34c31dfccf7bc4913b01f8dd3d4352045c1da8b4 Mon Sep 17 00:00:00 2001 From: liningrui Date: Fri, 19 Apr 2019 10:46:43 +0800 Subject: [PATCH 7/7] Use source as id directly Change-Id: Idf833f3fb02d3dc9deeef4ec3cf551cff7176b7e --- .../baidu/hugegraph/api/traverser/NeighborRankAPI.java | 7 ++++--- .../baidu/hugegraph/api/traverser/PersonalRankAPI.java | 9 +++++---- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/baidu/hugegraph/api/traverser/NeighborRankAPI.java b/src/main/java/com/baidu/hugegraph/api/traverser/NeighborRankAPI.java index 4095ca45..4c9f300b 100644 --- a/src/main/java/com/baidu/hugegraph/api/traverser/NeighborRankAPI.java +++ b/src/main/java/com/baidu/hugegraph/api/traverser/NeighborRankAPI.java @@ -23,7 +23,6 @@ import java.util.Arrays; import java.util.List; -import com.baidu.hugegraph.api.graph.GraphAPI; import com.baidu.hugegraph.api.traverser.structure.Ranks; import com.baidu.hugegraph.client.RestClient; import com.baidu.hugegraph.rest.RestResult; @@ -51,7 +50,7 @@ public List post(Request request) { public static class Request { @JsonProperty("source") - private String source; + private Object source; @JsonProperty("steps") private List steps; @JsonProperty("alpha") @@ -88,7 +87,9 @@ private Builder() { } public Builder source(Object source) { - this.request.source = GraphAPI.formatVertexId(source); + E.checkArgument(source != null, "The label of request " + + "for neighbor rank can't be null"); + this.request.source = source; return this; } diff --git a/src/main/java/com/baidu/hugegraph/api/traverser/PersonalRankAPI.java b/src/main/java/com/baidu/hugegraph/api/traverser/PersonalRankAPI.java index 5309ba98..40e38551 100644 --- a/src/main/java/com/baidu/hugegraph/api/traverser/PersonalRankAPI.java +++ b/src/main/java/com/baidu/hugegraph/api/traverser/PersonalRankAPI.java @@ -19,7 +19,6 @@ package com.baidu.hugegraph.api.traverser; -import com.baidu.hugegraph.api.graph.GraphAPI; import com.baidu.hugegraph.api.traverser.structure.Ranks; import com.baidu.hugegraph.client.RestClient; import com.baidu.hugegraph.rest.RestResult; @@ -46,7 +45,7 @@ public Ranks post(Request request) { public static class Request { @JsonProperty("source") - private String source; + private Object source; @JsonProperty("label") private String label; @JsonProperty("alpha") @@ -91,12 +90,14 @@ private Builder() { } public Builder source(Object source) { - this.request.source = GraphAPI.formatVertexId(source); + E.checkArgument(source != null, "The source of request " + + "for personal rank can't be null"); + this.request.source = source; return this; } public Builder label(String label) { - E.checkArgument(label != null, "The label of rank request " + + E.checkArgument(label != null, "The label of request " + "for personal rank can't be null"); this.request.label = label; return this;