diff --git a/hugegraph-api/pom.xml b/hugegraph-api/pom.xml
index a2a3e2f8cd..fa2fbefe9a 100644
--- a/hugegraph-api/pom.xml
+++ b/hugegraph-api/pom.xml
@@ -104,7 +104,7 @@
- 0.57.0.0
+ 0.58.0.0
diff --git a/hugegraph-api/src/main/java/com/baidu/hugegraph/api/traversers/AllShortestPathsAPI.java b/hugegraph-api/src/main/java/com/baidu/hugegraph/api/traversers/AllShortestPathsAPI.java
index 1f88ad4654..941042893e 100644
--- a/hugegraph-api/src/main/java/com/baidu/hugegraph/api/traversers/AllShortestPathsAPI.java
+++ b/hugegraph-api/src/main/java/com/baidu/hugegraph/api/traversers/AllShortestPathsAPI.java
@@ -19,6 +19,8 @@
package com.baidu.hugegraph.api.traversers;
+import java.util.List;
+
import static com.baidu.hugegraph.traversal.algorithm.HugeTraverser.DEFAULT_CAPACITY;
import static com.baidu.hugegraph.traversal.algorithm.HugeTraverser.DEFAULT_DEGREE;
@@ -45,6 +47,7 @@
import com.baidu.hugegraph.type.define.Directions;
import com.baidu.hugegraph.util.Log;
import com.codahale.metrics.annotation.Timed;
+import com.google.common.collect.ImmutableList;
@Path("graphs/{graph}/traversers/allshortestpaths")
@Singleton
@@ -81,9 +84,11 @@ public String get(@Context GraphManager manager,
HugeGraph g = graph(manager, graph);
ShortestPathTraverser traverser = new ShortestPathTraverser(g);
+ List edgeLabels = edgeLabel == null ? ImmutableList.of() :
+ ImmutableList.of(edgeLabel);
HugeTraverser.PathSet paths = traverser.allShortestPaths(
- sourceId, targetId, dir, edgeLabel, depth,
- degree, skipDegree, capacity);
+ sourceId, targetId, dir, edgeLabels,
+ depth, degree, skipDegree, capacity);
return manager.serializer(g).writePaths("paths", paths, false);
}
}
diff --git a/hugegraph-api/src/main/java/com/baidu/hugegraph/api/traversers/CustomizedCrosspointsAPI.java b/hugegraph-api/src/main/java/com/baidu/hugegraph/api/traversers/CustomizedCrosspointsAPI.java
index 26a4cf00de..293905a9fd 100644
--- a/hugegraph-api/src/main/java/com/baidu/hugegraph/api/traversers/CustomizedCrosspointsAPI.java
+++ b/hugegraph-api/src/main/java/com/baidu/hugegraph/api/traversers/CustomizedCrosspointsAPI.java
@@ -84,7 +84,7 @@ public String post(@Context GraphManager manager,
request.capacity, request.limit);
HugeGraph g = graph(manager, graph);
- Iterator sources = request.sources.sourcesVertices(g);
+ Iterator sources = request.sources.vertices(g);
List patterns;
patterns = pathPatterns(g, request);
@@ -132,7 +132,7 @@ public String post(@Context GraphManager manager,
private static class CrosspointsRequest {
@JsonProperty("sources")
- public SourceVertices sources;
+ public Vertices sources;
@JsonProperty("path_patterns")
public List pathPatterns;
@JsonProperty("capacity")
diff --git a/hugegraph-api/src/main/java/com/baidu/hugegraph/api/traversers/CustomizedPathsAPI.java b/hugegraph-api/src/main/java/com/baidu/hugegraph/api/traversers/CustomizedPathsAPI.java
index 8dfac69cd2..e49f808e0c 100644
--- a/hugegraph-api/src/main/java/com/baidu/hugegraph/api/traversers/CustomizedPathsAPI.java
+++ b/hugegraph-api/src/main/java/com/baidu/hugegraph/api/traversers/CustomizedPathsAPI.java
@@ -86,7 +86,7 @@ public String post(@Context GraphManager manager,
request.withVertex);
HugeGraph g = graph(manager, graph);
- Iterator sources = request.sources.sourcesVertices(g);
+ Iterator sources = request.sources.vertices(g);
List steps = step(g, request);
boolean sorted = request.sortBy != SortBy.NONE;
@@ -129,7 +129,7 @@ private static List step(HugeGraph graph,
private static class PathRequest {
@JsonProperty("sources")
- public SourceVertices sources;
+ public Vertices sources;
@JsonProperty("steps")
public List steps;
@JsonProperty("sort_by")
diff --git a/hugegraph-api/src/main/java/com/baidu/hugegraph/api/traversers/FusiformSimilarityAPI.java b/hugegraph-api/src/main/java/com/baidu/hugegraph/api/traversers/FusiformSimilarityAPI.java
index 0a56f56b82..e6ef2858b7 100644
--- a/hugegraph-api/src/main/java/com/baidu/hugegraph/api/traversers/FusiformSimilarityAPI.java
+++ b/hugegraph-api/src/main/java/com/baidu/hugegraph/api/traversers/FusiformSimilarityAPI.java
@@ -97,7 +97,7 @@ public String post(@Context GraphManager manager,
request.groupProperty, request.minGroups);
HugeGraph g = graph(manager, graph);
- Iterator sources = request.sources.sourcesVertices(g);
+ Iterator sources = request.sources.vertices(g);
E.checkArgument(sources != null && sources.hasNext(),
"The source vertices can't be empty");
EdgeLabel edgeLabel = request.label == null ?
@@ -125,7 +125,7 @@ public String post(@Context GraphManager manager,
private static class FusiformSimilarityRequest {
@JsonProperty("sources")
- public SourceVertices sources;
+ public Vertices sources;
@JsonProperty("label")
public String label;
@JsonProperty("direction")
diff --git a/hugegraph-api/src/main/java/com/baidu/hugegraph/api/traversers/JaccardSimilarityAPI.java b/hugegraph-api/src/main/java/com/baidu/hugegraph/api/traversers/JaccardSimilarityAPI.java
index 5c2449ce8d..c7ee87525f 100644
--- a/hugegraph-api/src/main/java/com/baidu/hugegraph/api/traversers/JaccardSimilarityAPI.java
+++ b/hugegraph-api/src/main/java/com/baidu/hugegraph/api/traversers/JaccardSimilarityAPI.java
@@ -19,11 +19,17 @@
package com.baidu.hugegraph.api.traversers;
+import java.util.Map;
+
+import static com.baidu.hugegraph.traversal.algorithm.HugeTraverser.DEFAULT_CAPACITY;
import static com.baidu.hugegraph.traversal.algorithm.HugeTraverser.DEFAULT_DEGREE;
+import static com.baidu.hugegraph.traversal.algorithm.HugeTraverser.DEFAULT_LIMIT;
import javax.inject.Singleton;
+import javax.ws.rs.Consumes;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
+import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
@@ -33,22 +39,25 @@
import org.slf4j.Logger;
import com.baidu.hugegraph.HugeGraph;
-import com.baidu.hugegraph.api.API;
import com.baidu.hugegraph.api.graph.EdgeAPI;
import com.baidu.hugegraph.api.graph.VertexAPI;
import com.baidu.hugegraph.backend.id.Id;
import com.baidu.hugegraph.core.GraphManager;
import com.baidu.hugegraph.server.RestServer;
-import com.baidu.hugegraph.traversal.algorithm.HugeTraverser;
+import com.baidu.hugegraph.structure.HugeVertex;
+import com.baidu.hugegraph.traversal.algorithm.EdgeStep;
+import com.baidu.hugegraph.traversal.algorithm.JaccardSimilarTraverser;
import com.baidu.hugegraph.type.define.Directions;
+import com.baidu.hugegraph.util.E;
import com.baidu.hugegraph.util.JsonUtil;
import com.baidu.hugegraph.util.Log;
import com.codahale.metrics.annotation.Timed;
+import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.collect.ImmutableMap;
@Path("graphs/{graph}/traversers/jaccardsimilarity")
@Singleton
-public class JaccardSimilarityAPI extends API {
+public class JaccardSimilarityAPI extends TraverserAPI {
private static final Logger LOG = Log.logger(RestServer.class);
@@ -72,10 +81,61 @@ public String get(@Context GraphManager manager,
Directions dir = Directions.convert(EdgeAPI.parseDirection(direction));
HugeGraph g = graph(manager, graph);
- HugeTraverser traverser = new HugeTraverser(g);
+ JaccardSimilarTraverser traverser = new JaccardSimilarTraverser(g);
double similarity = traverser.jaccardSimilarity(sourceId, targetId, dir,
edgeLabel, degree);
return JsonUtil.toJson(ImmutableMap.of("jaccard_similarity",
similarity));
}
+
+ @POST
+ @Timed
+ @Consumes(APPLICATION_JSON)
+ @Produces(APPLICATION_JSON_WITH_CHARSET)
+ public String post(@Context GraphManager manager,
+ @PathParam("graph") String graph,
+ Request request) {
+ E.checkArgumentNotNull(request, "The request body can't be null");
+ E.checkArgumentNotNull(request.vertex,
+ "The source vertex of request can't be null");
+ E.checkArgument(request.step != null,
+ "The steps of request can't be null");
+ E.checkArgument(request.top >= 0,
+ "The top must be >= 0, but got: %s", request.top);
+
+ LOG.debug("Graph [{}] get jaccard similars from source vertex '{}', " +
+ "with step '{}', top '{}' and capacity '{}'",
+ graph, request.vertex, request.step,
+ request.top, request.capacity);
+
+ HugeGraph g = graph(manager, graph);
+ Id sourceId = HugeVertex.getIdValue(request.vertex);
+
+ EdgeStep step = step(g, request.step);
+
+ JaccardSimilarTraverser traverser = new JaccardSimilarTraverser(g);
+ Map results = traverser.jaccardSimilars(sourceId, step,
+ request.top,
+ request.capacity);
+ return manager.serializer(g).writeMap(results);
+ }
+
+ private static class Request {
+
+ @JsonProperty("vertex")
+ public Object vertex;
+ @JsonProperty("step")
+ public TraverserAPI.Step step;
+ @JsonProperty("top")
+ public int top = Integer.valueOf(DEFAULT_LIMIT);
+ @JsonProperty("capacity")
+ public long capacity = Long.valueOf(DEFAULT_CAPACITY);
+
+ @Override
+ public String toString() {
+ return String.format("Request{vertex=%s,step=%s,top=%s," +
+ "capacity=%s}", this.vertex, this.step,
+ this.top, this.capacity);
+ }
+ }
}
diff --git a/hugegraph-api/src/main/java/com/baidu/hugegraph/api/traversers/KneighborAPI.java b/hugegraph-api/src/main/java/com/baidu/hugegraph/api/traversers/KneighborAPI.java
index 16ddb0b009..77822e7c3b 100644
--- a/hugegraph-api/src/main/java/com/baidu/hugegraph/api/traversers/KneighborAPI.java
+++ b/hugegraph-api/src/main/java/com/baidu/hugegraph/api/traversers/KneighborAPI.java
@@ -21,35 +21,48 @@
import static com.baidu.hugegraph.traversal.algorithm.HugeTraverser.DEFAULT_DEGREE;
import static com.baidu.hugegraph.traversal.algorithm.HugeTraverser.DEFAULT_ELEMENTS_LIMIT;
+import static com.baidu.hugegraph.traversal.algorithm.HugeTraverser.DEFAULT_PATHS_LIMIT;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
import java.util.Set;
import javax.inject.Singleton;
+import javax.ws.rs.Consumes;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
+import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
import org.slf4j.Logger;
import com.baidu.hugegraph.HugeGraph;
-import com.baidu.hugegraph.api.API;
import com.baidu.hugegraph.api.graph.EdgeAPI;
import com.baidu.hugegraph.api.graph.VertexAPI;
import com.baidu.hugegraph.backend.id.Id;
+import com.baidu.hugegraph.backend.query.QueryResults;
import com.baidu.hugegraph.core.GraphManager;
import com.baidu.hugegraph.server.RestServer;
+import com.baidu.hugegraph.structure.HugeVertex;
+import com.baidu.hugegraph.traversal.algorithm.KneighborTraverser;
+import com.baidu.hugegraph.traversal.algorithm.EdgeStep;
import com.baidu.hugegraph.traversal.algorithm.HugeTraverser;
import com.baidu.hugegraph.type.define.Directions;
+import com.baidu.hugegraph.util.E;
import com.baidu.hugegraph.util.Log;
import com.codahale.metrics.annotation.Timed;
+import com.fasterxml.jackson.annotation.JsonProperty;
@Path("graphs/{graph}/traversers/kneighbor")
@Singleton
-public class KneighborAPI extends API {
+public class KneighborAPI extends TraverserAPI {
private static final Logger LOG = Log.logger(RestServer.class);
@@ -77,9 +90,98 @@ public String get(@Context GraphManager manager,
HugeGraph g = graph(manager, graph);
- HugeTraverser traverser = new HugeTraverser(g);
+ KneighborTraverser traverser = new KneighborTraverser(g);
Set ids = traverser.kneighbor(source, dir, edgeLabel, depth,
degree, limit);
return manager.serializer(g).writeList("vertices", ids);
}
+
+ @POST
+ @Timed
+ @Consumes(APPLICATION_JSON)
+ @Produces(APPLICATION_JSON_WITH_CHARSET)
+ public String post(@Context GraphManager manager,
+ @PathParam("graph") String graph,
+ Request request) {
+ E.checkArgumentNotNull(request, "The request body can't be null");
+ E.checkArgumentNotNull(request.source,
+ "The source of request can't be null");
+ E.checkArgument(request.step != null,
+ "The steps of request can't be null");
+ if (request.countOnly) {
+ E.checkArgument(!request.withVertex && !request.withPath,
+ "Can't return vertex or path when count only");
+ }
+
+ LOG.debug("Graph [{}] get customized kneighbor from source vertex " +
+ "'{}', with step '{}', limit '{}', count_only '{}', " +
+ "with_vertex '{}' and with_path '{}'",
+ graph, request.source, request.step, request.limit,
+ request.countOnly, request.withVertex, request.withPath);
+
+ HugeGraph g = graph(manager, graph);
+ Id sourceId = HugeVertex.getIdValue(request.source);
+
+ EdgeStep step = step(g, request.step);
+
+ KneighborTraverser traverser = new KneighborTraverser(g);
+ Set results = traverser.customizedKneighbor(
+ sourceId, step, request.maxDepth,
+ request.limit);
+
+ Set neighbors = new HashSet<>();
+ for (HugeTraverser.Node node : results) {
+ neighbors.add(node.id());
+ }
+
+ List paths = new ArrayList<>();
+ if (request.withPath) {
+ for (HugeTraverser.Node node : results) {
+ paths.add(new HugeTraverser.Path(node.path()));
+ }
+ }
+ Iterator iter = QueryResults.emptyIterator();
+ if (request.withVertex) {
+ Set ids = new HashSet<>();
+ for (HugeTraverser.Node node : results) {
+ ids.add(node.id());
+ }
+ for (HugeTraverser.Path p : paths) {
+ ids.addAll(p.vertices());
+ }
+ if (!ids.isEmpty()) {
+ iter = g.vertices(ids.toArray());
+ }
+ }
+ return manager.serializer(g).writeNodesWithPath("kneighbor", neighbors,
+ paths, iter,
+ request.countOnly);
+ }
+
+ private static class Request {
+
+ @JsonProperty("source")
+ public Object source;
+ @JsonProperty("step")
+ public TraverserAPI.Step step;
+ @JsonProperty("max_depth")
+ public int maxDepth;
+ @JsonProperty("limit")
+ public long limit = Long.valueOf(DEFAULT_PATHS_LIMIT);
+ @JsonProperty("count_only")
+ public boolean countOnly = false;
+ @JsonProperty("with_vertex")
+ public boolean withVertex = false;
+ @JsonProperty("with_path")
+ public boolean withPath = false;
+
+ @Override
+ public String toString() {
+ return String.format("PathRequest{source=%s,step=%s,maxDepth=%s" +
+ "limit=%s,countOnly=%s,withVertex=%s," +
+ "withPath=%s}", this.source, this.step,
+ this.maxDepth, this.limit, this.countOnly,
+ this.withVertex, this.withPath);
+ }
+ }
}
diff --git a/hugegraph-api/src/main/java/com/baidu/hugegraph/api/traversers/KoutAPI.java b/hugegraph-api/src/main/java/com/baidu/hugegraph/api/traversers/KoutAPI.java
index 6f15c1944b..eb7aa401f8 100644
--- a/hugegraph-api/src/main/java/com/baidu/hugegraph/api/traversers/KoutAPI.java
+++ b/hugegraph-api/src/main/java/com/baidu/hugegraph/api/traversers/KoutAPI.java
@@ -19,38 +19,52 @@
package com.baidu.hugegraph.api.traversers;
-import static com.baidu.hugegraph.traversal.algorithm.HugeTraverser.DEFAULT_CAPACITY;
-import static com.baidu.hugegraph.traversal.algorithm.HugeTraverser.DEFAULT_DEGREE;
-import static com.baidu.hugegraph.traversal.algorithm.HugeTraverser.DEFAULT_ELEMENTS_LIMIT;
-
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
import java.util.Set;
import javax.inject.Singleton;
+import javax.ws.rs.Consumes;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
+import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
import org.slf4j.Logger;
import com.baidu.hugegraph.HugeGraph;
-import com.baidu.hugegraph.api.API;
import com.baidu.hugegraph.api.graph.EdgeAPI;
import com.baidu.hugegraph.api.graph.VertexAPI;
import com.baidu.hugegraph.backend.id.Id;
+import com.baidu.hugegraph.backend.query.QueryResults;
import com.baidu.hugegraph.core.GraphManager;
import com.baidu.hugegraph.server.RestServer;
+import com.baidu.hugegraph.structure.HugeVertex;
+import com.baidu.hugegraph.traversal.algorithm.KoutTraverser;
+import com.baidu.hugegraph.traversal.algorithm.EdgeStep;
import com.baidu.hugegraph.traversal.algorithm.HugeTraverser;
import com.baidu.hugegraph.type.define.Directions;
+import com.baidu.hugegraph.util.E;
import com.baidu.hugegraph.util.Log;
import com.codahale.metrics.annotation.Timed;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import static com.baidu.hugegraph.traversal.algorithm.HugeTraverser.Node;
+import static com.baidu.hugegraph.traversal.algorithm.HugeTraverser.DEFAULT_CAPACITY;
+import static com.baidu.hugegraph.traversal.algorithm.HugeTraverser.DEFAULT_DEGREE;
+import static com.baidu.hugegraph.traversal.algorithm.HugeTraverser.DEFAULT_ELEMENTS_LIMIT;
+import static com.baidu.hugegraph.traversal.algorithm.HugeTraverser.DEFAULT_PATHS_LIMIT;
@Path("graphs/{graph}/traversers/kout")
@Singleton
-public class KoutAPI extends API {
+public class KoutAPI extends TraverserAPI {
private static final Logger LOG = Log.logger(RestServer.class);
@@ -82,9 +96,106 @@ public String get(@Context GraphManager manager,
HugeGraph g = graph(manager, graph);
- HugeTraverser traverser = new HugeTraverser(g);
+ KoutTraverser traverser = new KoutTraverser(g);
Set ids = traverser.kout(sourceId, dir, edgeLabel, depth,
nearest, degree, capacity, limit);
return manager.serializer(g).writeList("vertices", ids);
}
+
+ @POST
+ @Timed
+ @Consumes(APPLICATION_JSON)
+ @Produces(APPLICATION_JSON_WITH_CHARSET)
+ public String post(@Context GraphManager manager,
+ @PathParam("graph") String graph,
+ Request request) {
+ E.checkArgumentNotNull(request, "The request body can't be null");
+ E.checkArgumentNotNull(request.source,
+ "The source of request can't be null");
+ E.checkArgument(request.step != null,
+ "The steps of request can't be null");
+ if (request.countOnly) {
+ E.checkArgument(!request.withVertex && !request.withPath,
+ "Can't return vertex or path when count only");
+ }
+
+ LOG.debug("Graph [{}] get customized kout from source vertex '{}', " +
+ "with step '{}', max_depth '{}', nearest '{}', " +
+ "count_only '{}', capacity '{}', limit '{}', " +
+ "with_vertex '{}' and with_path '{}'",
+ graph, request.source, request.step, request.maxDepth,
+ request.nearest, request.countOnly, request.capacity,
+ request.limit, request.withVertex, request.withPath);
+
+ HugeGraph g = graph(manager, graph);
+ Id sourceId = HugeVertex.getIdValue(request.source);
+
+ EdgeStep step = step(g, request.step);
+
+ KoutTraverser traverser = new KoutTraverser(g);
+ Set results = traverser.customizedKout(
+ sourceId, step, request.maxDepth,
+ request.nearest, request.capacity,
+ request.limit);
+
+ Set neighbors = new HashSet<>();
+ for (HugeTraverser.Node node : results) {
+ neighbors.add(node.id());
+ }
+
+ List paths = new ArrayList<>();
+ if (request.withPath) {
+ for (HugeTraverser.Node node : results) {
+ paths.add(new HugeTraverser.Path(node.path()));
+ }
+ }
+ Iterator iter = QueryResults.emptyIterator();
+ if (request.withVertex) {
+ Set ids = new HashSet<>();
+ for (Node node : results) {
+ ids.add(node.id());
+ }
+ for (HugeTraverser.Path p : paths) {
+ ids.addAll(p.vertices());
+ }
+ if (!ids.isEmpty()) {
+ iter = g.vertices(ids.toArray());
+ }
+ }
+ return manager.serializer(g).writeNodesWithPath("kout", neighbors,
+ paths, iter,
+ request.countOnly);
+ }
+
+ private static class Request {
+
+ @JsonProperty("source")
+ public Object source;
+ @JsonProperty("step")
+ public TraverserAPI.Step step;
+ @JsonProperty("max_depth")
+ public int maxDepth;
+ @JsonProperty("nearest")
+ public boolean nearest = true;
+ @JsonProperty("count_only")
+ public boolean countOnly = false;
+ @JsonProperty("capacity")
+ public long capacity = Long.valueOf(DEFAULT_CAPACITY);
+ @JsonProperty("limit")
+ public long limit = Long.valueOf(DEFAULT_PATHS_LIMIT);
+ @JsonProperty("with_vertex")
+ public boolean withVertex = false;
+ @JsonProperty("with_path")
+ public boolean withPath = false;
+
+ @Override
+ public String toString() {
+ return String.format("KoutRequest{source=%s,step=%s,maxDepth=%s" +
+ "nearest=%s,countOnly=%s,capacity=%s," +
+ "limit=%s,withVertex=%s,withPath=%s}",
+ this.source, this.step, this.maxDepth,
+ this.nearest, this.countOnly, this.capacity,
+ this.limit, this.withVertex, this.withPath);
+ }
+ }
}
diff --git a/hugegraph-api/src/main/java/com/baidu/hugegraph/api/traversers/MultiNodeShortestPathAPI.java b/hugegraph-api/src/main/java/com/baidu/hugegraph/api/traversers/MultiNodeShortestPathAPI.java
new file mode 100644
index 0000000000..c3cebec720
--- /dev/null
+++ b/hugegraph-api/src/main/java/com/baidu/hugegraph/api/traversers/MultiNodeShortestPathAPI.java
@@ -0,0 +1,126 @@
+/*
+ * 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.traversers;
+
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import javax.inject.Singleton;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.slf4j.Logger;
+
+import com.baidu.hugegraph.HugeGraph;
+import com.baidu.hugegraph.backend.id.Id;
+import com.baidu.hugegraph.backend.query.QueryResults;
+import com.baidu.hugegraph.core.GraphManager;
+import com.baidu.hugegraph.server.RestServer;
+import com.baidu.hugegraph.traversal.algorithm.EdgeStep;
+import com.baidu.hugegraph.traversal.algorithm.HugeTraverser;
+import com.baidu.hugegraph.traversal.algorithm.MultiNodeShortestPathTraverser;
+import com.baidu.hugegraph.util.E;
+import com.baidu.hugegraph.util.Log;
+import com.codahale.metrics.annotation.Timed;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import static com.baidu.hugegraph.traversal.algorithm.HugeTraverser.DEFAULT_CAPACITY;
+
+@Path("graphs/{graph}/traversers/multinodeshortestpath")
+@Singleton
+public class MultiNodeShortestPathAPI extends TraverserAPI {
+
+ private static final Logger LOG = Log.logger(RestServer.class);
+
+ @POST
+ @Timed
+ @Consumes(APPLICATION_JSON)
+ @Produces(APPLICATION_JSON_WITH_CHARSET)
+ public String post(@Context GraphManager manager,
+ @PathParam("graph") String graph,
+ Request request) {
+ E.checkArgumentNotNull(request, "The request body can't be null");
+ E.checkArgumentNotNull(request.vertices,
+ "The vertices of request can't be null");
+ E.checkArgument(request.step != null,
+ "The steps of request can't be null");
+
+ LOG.debug("Graph [{}] get multiple node shortest path from " +
+ "vertices '{}', with step '{}', max_depth '{}', capacity " +
+ "'{}' and with_vertex '{}'",
+ graph, request.vertices, request.step, request.maxDepth,
+ request.capacity, request.withVertex);
+
+ HugeGraph g = graph(manager, graph);
+ Iterator vertices = request.vertices.vertices(g);
+
+ EdgeStep step = step(g, request.step);
+
+ MultiNodeShortestPathTraverser traverser =
+ new MultiNodeShortestPathTraverser(g);
+ List paths;
+ paths = traverser.multiNodeShortestPath(vertices, step,
+ request.maxDepth,
+ request.capacity);
+
+ if (!request.withVertex) {
+ return manager.serializer(g).writePaths("paths", paths, false);
+ }
+
+ Set ids = new HashSet<>();
+ for (HugeTraverser.Path p : paths) {
+ ids.addAll(p.vertices());
+ }
+ Iterator iter = QueryResults.emptyIterator();
+ if (!ids.isEmpty()) {
+ iter = g.vertices(ids.toArray());
+ }
+ return manager.serializer(g).writePaths("paths", paths, false, iter);
+ }
+
+ private static class Request {
+
+ @JsonProperty("vertices")
+ public Vertices vertices;
+ @JsonProperty("step")
+ public Step step;
+ @JsonProperty("max_depth")
+ public int maxDepth;
+ @JsonProperty("capacity")
+ public long capacity = Long.valueOf(DEFAULT_CAPACITY);
+ @JsonProperty("with_vertex")
+ public boolean withVertex = false;
+
+ @Override
+ public String toString() {
+ return String.format("Request{vertices=%s,step=%s,maxDepth=%s" +
+ "capacity=%s,withVertex=%s}",
+ this.vertices, this.step, this.maxDepth,
+ this.capacity, this.withVertex);
+ }
+ }
+}
diff --git a/hugegraph-api/src/main/java/com/baidu/hugegraph/api/traversers/PathsAPI.java b/hugegraph-api/src/main/java/com/baidu/hugegraph/api/traversers/PathsAPI.java
index e54367fcee..27ea55b2eb 100644
--- a/hugegraph-api/src/main/java/com/baidu/hugegraph/api/traversers/PathsAPI.java
+++ b/hugegraph-api/src/main/java/com/baidu/hugegraph/api/traversers/PathsAPI.java
@@ -19,37 +19,49 @@
package com.baidu.hugegraph.api.traversers;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
import static com.baidu.hugegraph.traversal.algorithm.HugeTraverser.DEFAULT_CAPACITY;
import static com.baidu.hugegraph.traversal.algorithm.HugeTraverser.DEFAULT_DEGREE;
import static com.baidu.hugegraph.traversal.algorithm.HugeTraverser.DEFAULT_PATHS_LIMIT;
import javax.inject.Singleton;
+import javax.ws.rs.Consumes;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
+import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
import org.slf4j.Logger;
import com.baidu.hugegraph.HugeGraph;
-import com.baidu.hugegraph.api.API;
import com.baidu.hugegraph.api.graph.EdgeAPI;
import com.baidu.hugegraph.api.graph.VertexAPI;
import com.baidu.hugegraph.backend.id.Id;
+import com.baidu.hugegraph.backend.query.QueryResults;
import com.baidu.hugegraph.core.GraphManager;
import com.baidu.hugegraph.server.RestServer;
+import com.baidu.hugegraph.traversal.algorithm.CollectionPathsTraverser;
+import com.baidu.hugegraph.traversal.algorithm.EdgeStep;
import com.baidu.hugegraph.traversal.algorithm.HugeTraverser;
import com.baidu.hugegraph.traversal.algorithm.PathsTraverser;
import com.baidu.hugegraph.type.define.Directions;
+import com.baidu.hugegraph.util.E;
import com.baidu.hugegraph.util.Log;
import com.codahale.metrics.annotation.Timed;
+import com.fasterxml.jackson.annotation.JsonProperty;
@Path("graphs/{graph}/traversers/paths")
@Singleton
-public class PathsAPI extends API {
+public class PathsAPI extends TraverserAPI {
private static final Logger LOG = Log.logger(RestServer.class);
@@ -87,4 +99,85 @@ public String get(@Context GraphManager manager,
limit);
return manager.serializer(g).writePaths("paths", paths, false);
}
+
+ @POST
+ @Timed
+ @Consumes(APPLICATION_JSON)
+ @Produces(APPLICATION_JSON_WITH_CHARSET)
+ public String post(@Context GraphManager manager,
+ @PathParam("graph") String graph,
+ Request request) {
+ E.checkArgumentNotNull(request, "The request body can't be null");
+ E.checkArgumentNotNull(request.sources,
+ "The sources of request can't be null");
+ E.checkArgumentNotNull(request.targets,
+ "The targets of request can't be null");
+ E.checkArgumentNotNull(request.step,
+ "The step of request can't be null");
+ E.checkArgument(request.depth > 0,
+ "The depth of request must be > 0, but got: %s",
+ request.depth);
+
+ LOG.debug("Graph [{}] get paths from source vertices '{}', target " +
+ "vertices '{}', with step '{}', max depth '{}', " +
+ "capacity '{}', limit '{}' and with_vertex '{}'",
+ graph, request.sources, request.targets, request.step,
+ request.depth, request.capacity, request.limit,
+ request.withVertex);
+
+ HugeGraph g = graph(manager, graph);
+ Iterator sources = request.sources.vertices(g);
+ Iterator targets = request.targets.vertices(g);
+ EdgeStep step = step(g, request.step);
+
+ CollectionPathsTraverser traverser = new CollectionPathsTraverser(g);
+ Collection paths;
+ paths = traverser.paths(sources, targets, step, request.depth,
+ request.nearest, request.capacity,
+ request.limit);
+
+ if (!request.withVertex) {
+ return manager.serializer(g).writePaths("paths", paths, false);
+ }
+
+ Set ids = new HashSet<>();
+ for (HugeTraverser.Path p : paths) {
+ ids.addAll(p.vertices());
+ }
+ Iterator iter = QueryResults.emptyIterator();
+ if (!ids.isEmpty()) {
+ iter = g.vertices(ids.toArray());
+ }
+ return manager.serializer(g).writePaths("paths", paths, false, iter);
+ }
+
+ private static class Request {
+
+ @JsonProperty("sources")
+ public Vertices sources;
+ @JsonProperty("targets")
+ public Vertices targets;
+ @JsonProperty("step")
+ public TraverserAPI.Step step;
+ @JsonProperty("max_depth")
+ public int depth;
+ @JsonProperty("nearest")
+ public boolean nearest = false;
+ @JsonProperty("capacity")
+ public long capacity = Long.valueOf(DEFAULT_CAPACITY);
+ @JsonProperty("limit")
+ public long limit = Long.valueOf(DEFAULT_PATHS_LIMIT);
+ @JsonProperty("with_vertex")
+ public boolean withVertex = false;
+
+ @Override
+ public String toString() {
+ return String.format("PathRequest{sources=%s,targets=%s,step=%s," +
+ "maxDepth=%s,nearest=%s,capacity=%s," +
+ "limit=%s,withVertex=%s}", this.sources,
+ this.targets, this.step, this.depth,
+ this.nearest, this.capacity,
+ this.limit, this.withVertex);
+ }
+ }
}
diff --git a/hugegraph-api/src/main/java/com/baidu/hugegraph/api/traversers/SameNeighborsAPI.java b/hugegraph-api/src/main/java/com/baidu/hugegraph/api/traversers/SameNeighborsAPI.java
index ca449c4564..0c6c3c1b83 100644
--- a/hugegraph-api/src/main/java/com/baidu/hugegraph/api/traversers/SameNeighborsAPI.java
+++ b/hugegraph-api/src/main/java/com/baidu/hugegraph/api/traversers/SameNeighborsAPI.java
@@ -42,7 +42,7 @@
import com.baidu.hugegraph.backend.id.Id;
import com.baidu.hugegraph.core.GraphManager;
import com.baidu.hugegraph.server.RestServer;
-import com.baidu.hugegraph.traversal.algorithm.HugeTraverser;
+import com.baidu.hugegraph.traversal.algorithm.SameNeighborTraverser;
import com.baidu.hugegraph.type.define.Directions;
import com.baidu.hugegraph.util.Log;
import com.codahale.metrics.annotation.Timed;
@@ -75,7 +75,7 @@ public String get(@Context GraphManager manager,
Directions dir = Directions.convert(EdgeAPI.parseDirection(direction));
HugeGraph g = graph(manager, graph);
- HugeTraverser traverser = new HugeTraverser(g);
+ SameNeighborTraverser traverser = new SameNeighborTraverser(g);
Set neighbors = traverser.sameNeighbors(sourceId, targetId, dir,
edgeLabel, degree, limit);
return manager.serializer(g).writeList("same_neighbors", neighbors);
diff --git a/hugegraph-api/src/main/java/com/baidu/hugegraph/api/traversers/ShortestPathAPI.java b/hugegraph-api/src/main/java/com/baidu/hugegraph/api/traversers/ShortestPathAPI.java
index ab10da79cd..fa97a93e23 100644
--- a/hugegraph-api/src/main/java/com/baidu/hugegraph/api/traversers/ShortestPathAPI.java
+++ b/hugegraph-api/src/main/java/com/baidu/hugegraph/api/traversers/ShortestPathAPI.java
@@ -19,6 +19,8 @@
package com.baidu.hugegraph.api.traversers;
+import java.util.List;
+
import static com.baidu.hugegraph.traversal.algorithm.HugeTraverser.DEFAULT_CAPACITY;
import static com.baidu.hugegraph.traversal.algorithm.HugeTraverser.DEFAULT_DEGREE;
@@ -45,6 +47,7 @@
import com.baidu.hugegraph.type.define.Directions;
import com.baidu.hugegraph.util.Log;
import com.codahale.metrics.annotation.Timed;
+import com.google.common.collect.ImmutableList;
@Path("graphs/{graph}/traversers/shortestpath")
@Singleton
@@ -81,8 +84,11 @@ public String get(@Context GraphManager manager,
HugeGraph g = graph(manager, graph);
ShortestPathTraverser traverser = new ShortestPathTraverser(g);
+
+ List edgeLabels = edgeLabel == null ? ImmutableList.of() :
+ ImmutableList.of(edgeLabel);
HugeTraverser.Path path = traverser.shortestPath(sourceId, targetId,
- dir, edgeLabel, depth,
+ dir, edgeLabels, depth,
degree, skipDegree,
capacity);
return manager.serializer(g).writeList("path", path.vertices());
diff --git a/hugegraph-api/src/main/java/com/baidu/hugegraph/api/traversers/TemplatePathsAPI.java b/hugegraph-api/src/main/java/com/baidu/hugegraph/api/traversers/TemplatePathsAPI.java
new file mode 100644
index 0000000000..c0e13d8fc0
--- /dev/null
+++ b/hugegraph-api/src/main/java/com/baidu/hugegraph/api/traversers/TemplatePathsAPI.java
@@ -0,0 +1,160 @@
+/*
+ * 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.traversers;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import javax.inject.Singleton;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.slf4j.Logger;
+
+import com.baidu.hugegraph.HugeGraph;
+import com.baidu.hugegraph.backend.id.Id;
+import com.baidu.hugegraph.backend.query.QueryResults;
+import com.baidu.hugegraph.core.GraphManager;
+import com.baidu.hugegraph.server.RestServer;
+import com.baidu.hugegraph.traversal.algorithm.HugeTraverser;
+import com.baidu.hugegraph.traversal.algorithm.TemplatePathsTraverser;
+import com.baidu.hugegraph.util.E;
+import com.baidu.hugegraph.util.Log;
+import com.codahale.metrics.annotation.Timed;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import static com.baidu.hugegraph.traversal.algorithm.HugeTraverser.DEFAULT_CAPACITY;
+import static com.baidu.hugegraph.traversal.algorithm.HugeTraverser.DEFAULT_PATHS_LIMIT;
+
+@Path("graphs/{graph}/traversers/templatepaths")
+@Singleton
+public class TemplatePathsAPI extends TraverserAPI {
+
+ private static final Logger LOG = Log.logger(RestServer.class);
+
+ @POST
+ @Timed
+ @Consumes(APPLICATION_JSON)
+ @Produces(APPLICATION_JSON_WITH_CHARSET)
+ public String post(@Context GraphManager manager,
+ @PathParam("graph") String graph,
+ Request request) {
+ E.checkArgumentNotNull(request, "The request body can't be null");
+ E.checkArgumentNotNull(request.sources,
+ "The sources of request can't be null");
+ E.checkArgumentNotNull(request.targets,
+ "The targets of request can't be null");
+ E.checkArgument(request.steps != null && !request.steps.isEmpty(),
+ "The steps of request can't be empty");
+
+ LOG.debug("Graph [{}] get template paths from source vertices '{}', " +
+ "target vertices '{}', with steps '{}', " +
+ "capacity '{}', limit '{}' and with_vertex '{}'",
+ graph, request.sources, request.targets, request.steps,
+ request.capacity, request.limit, request.withVertex);
+
+ HugeGraph g = graph(manager, graph);
+ Iterator sources = request.sources.vertices(g);
+ Iterator targets = request.targets.vertices(g);
+ List steps =
+ steps(g, request.steps);
+
+ TemplatePathsTraverser traverser = new TemplatePathsTraverser(g);
+ Set paths;
+ paths = traverser.templatePaths(sources, targets, steps,
+ request.withRing, request.capacity,
+ request.limit);
+
+ if (!request.withVertex) {
+ return manager.serializer(g).writePaths("paths", paths, false);
+ }
+
+ Set ids = new HashSet<>();
+ for (HugeTraverser.Path p : paths) {
+ ids.addAll(p.vertices());
+ }
+ Iterator iter = QueryResults.emptyIterator();
+ if (!ids.isEmpty()) {
+ iter = g.vertices(ids.toArray());
+ }
+ return manager.serializer(g).writePaths("paths", paths, false, iter);
+ }
+
+ private static List steps(
+ HugeGraph g, List steps) {
+ List edgeSteps =
+ new ArrayList<>(steps.size());
+ for (RepeatEdgeStep step : steps) {
+ edgeSteps.add(repeatEdgeStep(g, step));
+ }
+ return edgeSteps;
+ }
+
+ private static class Request {
+
+ @JsonProperty("sources")
+ public Vertices sources;
+ @JsonProperty("targets")
+ public Vertices targets;
+ @JsonProperty("steps")
+ public List steps;
+ @JsonProperty("with_ring")
+ public boolean withRing = false;
+ @JsonProperty("capacity")
+ public long capacity = Long.valueOf(DEFAULT_CAPACITY);
+ @JsonProperty("limit")
+ public long limit = Long.valueOf(DEFAULT_PATHS_LIMIT);
+ @JsonProperty("with_vertex")
+ public boolean withVertex = false;
+
+ @Override
+ public String toString() {
+ return String.format("TemplatePathsRequest{sources=%s,targets=%s," +
+ "steps=%s,withRing=%s,capacity=%s,limit=%s," +
+ "withVertex=%s}",
+ this.sources, this.targets, this.steps,
+ this.withRing, this.capacity, this.limit,
+ this.withVertex);
+ }
+ }
+
+ protected static class RepeatEdgeStep extends Step {
+
+ @JsonProperty("max_times")
+ public int maxTimes = 1;
+
+ @Override
+ public String toString() {
+ return String.format("RepeatEdgeStep{direction=%s,labels=%s," +
+ "properties=%s,degree=%s,skipDegree=%s," +
+ "maxTimes=%s}",
+ this.direction, this.labels, this.properties,
+ this.degree, this.skipDegree, this.maxTimes);
+ }
+ }
+}
diff --git a/hugegraph-api/src/main/java/com/baidu/hugegraph/api/traversers/TraverserAPI.java b/hugegraph-api/src/main/java/com/baidu/hugegraph/api/traversers/TraverserAPI.java
new file mode 100644
index 0000000000..c9af8595da
--- /dev/null
+++ b/hugegraph-api/src/main/java/com/baidu/hugegraph/api/traversers/TraverserAPI.java
@@ -0,0 +1,72 @@
+/*
+ * 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.traversers;
+
+import java.util.List;
+import java.util.Map;
+
+import com.baidu.hugegraph.HugeGraph;
+import com.baidu.hugegraph.api.API;
+import com.baidu.hugegraph.traversal.algorithm.EdgeStep;
+import com.baidu.hugegraph.traversal.algorithm.TemplatePathsTraverser;
+import com.baidu.hugegraph.type.define.Directions;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import static com.baidu.hugegraph.traversal.algorithm.HugeTraverser.DEFAULT_DEGREE;
+
+public class TraverserAPI extends API {
+
+ protected static EdgeStep step(HugeGraph graph, Step step) {
+ return new EdgeStep(graph, step.direction, step.labels, step.properties,
+ step.degree, step.skipDegree);
+ }
+
+ protected static TemplatePathsTraverser.RepeatEdgeStep repeatEdgeStep(
+ HugeGraph graph, TemplatePathsAPI.RepeatEdgeStep step) {
+ return new TemplatePathsTraverser.RepeatEdgeStep(graph, step.direction,
+ step.labels,
+ step.properties,
+ step.degree,
+ step.skipDegree,
+ step.maxTimes);
+ }
+
+ protected static class Step {
+
+ @JsonProperty("direction")
+ public Directions direction;
+ @JsonProperty("labels")
+ public List labels;
+ @JsonProperty("properties")
+ public Map properties;
+ @JsonProperty("degree")
+ public long degree = Long.valueOf(DEFAULT_DEGREE);
+ @JsonProperty("skip_degree")
+ public long skipDegree = 0L;
+
+ @Override
+ public String toString() {
+ return String.format("Step{direction=%s,labels=%s,properties=%s," +
+ "degree=%s,skipDegree=%s}",
+ this.direction, this.labels, this.properties,
+ this.degree, this.skipDegree);
+ }
+ }
+}
diff --git a/hugegraph-api/src/main/java/com/baidu/hugegraph/api/traversers/SourceVertices.java b/hugegraph-api/src/main/java/com/baidu/hugegraph/api/traversers/Vertices.java
similarity index 97%
rename from hugegraph-api/src/main/java/com/baidu/hugegraph/api/traversers/SourceVertices.java
rename to hugegraph-api/src/main/java/com/baidu/hugegraph/api/traversers/Vertices.java
index 65b24d48b4..4c0a0f5685 100644
--- a/hugegraph-api/src/main/java/com/baidu/hugegraph/api/traversers/SourceVertices.java
+++ b/hugegraph-api/src/main/java/com/baidu/hugegraph/api/traversers/Vertices.java
@@ -37,7 +37,7 @@
import com.baidu.hugegraph.util.E;
import com.fasterxml.jackson.annotation.JsonProperty;
-public class SourceVertices {
+public class Vertices {
@JsonProperty("ids")
public Set