From 09c5b81e909a7d16b127c67694f968ccf9044573 Mon Sep 17 00:00:00 2001 From: Jade Peng Date: Thu, 12 May 2022 14:38:56 +0800 Subject: [PATCH 1/5] feat: support query data by use cypher language (#1866) implement #1748 Co-authored-by: jadepeng --- hugegraph-api/pom.xml | 8 +- .../hugegraph/api/gremlin/CypherAPI.java | 93 +++++++++++++++++++ .../hugegraph/api/gremlin/GremlinAPI.java | 45 +-------- .../api/gremlin/GremlinQueryAPI.java | 90 ++++++++++++++++++ .../baidu/hugegraph/version/ApiVersion.java | 6 +- .../com/baidu/hugegraph/api/BaseApiTest.java | 2 +- .../baidu/hugegraph/api/CypherApiTest.java | 86 +++++++++++++++++ 7 files changed, 281 insertions(+), 49 deletions(-) create mode 100644 hugegraph-api/src/main/java/com/baidu/hugegraph/api/gremlin/CypherAPI.java create mode 100644 hugegraph-api/src/main/java/com/baidu/hugegraph/api/gremlin/GremlinQueryAPI.java create mode 100644 hugegraph-test/src/main/java/com/baidu/hugegraph/api/CypherApiTest.java diff --git a/hugegraph-api/pom.xml b/hugegraph-api/pom.xml index df88240d55..fab02997c6 100644 --- a/hugegraph-api/pom.xml +++ b/hugegraph-api/pom.xml @@ -104,7 +104,11 @@ ${pdclient.version} compile - + + org.opencypher.gremlin + translation + 1.0.4 + @@ -143,7 +147,7 @@ - 0.67.0.0 + 0.69.0.0 diff --git a/hugegraph-api/src/main/java/com/baidu/hugegraph/api/gremlin/CypherAPI.java b/hugegraph-api/src/main/java/com/baidu/hugegraph/api/gremlin/CypherAPI.java new file mode 100644 index 0000000000..f85ae03785 --- /dev/null +++ b/hugegraph-api/src/main/java/com/baidu/hugegraph/api/gremlin/CypherAPI.java @@ -0,0 +1,93 @@ +package com.baidu.hugegraph.api.gremlin; + +import org.opencypher.gremlin.translation.TranslationFacade; +import org.slf4j.Logger; + +import com.baidu.hugegraph.api.filter.CompressInterceptor; +import com.baidu.hugegraph.util.E; +import com.baidu.hugegraph.util.Log; +import com.codahale.metrics.annotation.Timed; + +import jakarta.inject.Singleton; +import jakarta.ws.rs.Consumes; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.PathParam; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.QueryParam; +import jakarta.ws.rs.core.Context; +import jakarta.ws.rs.core.HttpHeaders; +import jakarta.ws.rs.core.Response; + +@Path("graphs/{graph}/cypher") +@Singleton +public class CypherAPI extends GremlinQueryAPI { + + private static final Logger LOG = Log.logger(CypherAPI.class); + + + @GET + @Timed + @CompressInterceptor.Compress(buffer = (1024 * 40)) + @Produces(APPLICATION_JSON_WITH_CHARSET) + public Response query(@PathParam("graph") String graph, + @Context HttpHeaders headers, + @QueryParam("cypher") String cypher) { + LOG.debug("Graph [{}] query by cypher: {}", graph, cypher); + + return this.queryByCypher(graph, headers, cypher); + } + + @POST + @Timed + @CompressInterceptor.Compress + @Consumes(APPLICATION_JSON) + @Produces(APPLICATION_JSON_WITH_CHARSET) + public Response post(@PathParam("graph") String graph, + @Context HttpHeaders headers, + String cypher) { + LOG.debug("Graph [{}] query by cypher: {}", graph, cypher); + return this.queryByCypher(graph, headers, cypher); + } + + private Response queryByCypher(String graph, + HttpHeaders headers, + String cypher) { + E.checkArgument(cypher != null && !cypher.isEmpty(), + "The cypher parameter can't be null or empty"); + + String gremlin = this.translateCpyher2Gremlin(graph, cypher); + LOG.debug("translated gremlin is {}", gremlin); + + String auth = headers.getHeaderString(HttpHeaders.AUTHORIZATION); + String request = "{" + + "\"gremlin\":\"" + gremlin + "\"," + + "\"bindings\":{}," + + "\"language\":\"gremlin-groovy\"," + + "\"aliases\":{\"g\":\"__g_" + graph + "\"}}"; + + Response response = this.client().doPostRequest(auth, request); + return transformResponseIfNeeded(response); + } + + private String translateCpyher2Gremlin(String graph, String cypher) { + TranslationFacade translator = new TranslationFacade(); + String gremlin = translator.toGremlinGroovy(cypher); + gremlin = this.buildQueryableGremlin(graph, gremlin); + return gremlin; + } + + private String buildQueryableGremlin(String graph, String gremlin) { + /* + * `CREATE (a:person { name : 'test', age: 20) return a` + * would be translated to: + * `g.addV('person').as('a').property(single, 'name', 'test') ...`, + * but hugegraph don't support `.property(single, k, v)`, + * so we replace it to `.property(k, v)` here + */ + gremlin = gremlin.replace(".property(single,", ".property("); + + return gremlin; + } +} diff --git a/hugegraph-api/src/main/java/com/baidu/hugegraph/api/gremlin/GremlinAPI.java b/hugegraph-api/src/main/java/com/baidu/hugegraph/api/gremlin/GremlinAPI.java index b3928ed953..a72cbad7a1 100644 --- a/hugegraph-api/src/main/java/com/baidu/hugegraph/api/gremlin/GremlinAPI.java +++ b/hugegraph-api/src/main/java/com/baidu/hugegraph/api/gremlin/GremlinAPI.java @@ -45,13 +45,12 @@ @Path("gremlin") @Singleton -public class GremlinAPI extends API { +public class GremlinAPI extends GremlinQueryAPI { private static final Histogram gremlinInputHistogram = MetricsUtil.registerHistogram(GremlinAPI.class, "gremlin-input"); private static final Histogram gremlinOutputHistogram = MetricsUtil.registerHistogram(GremlinAPI.class, "gremlin-output"); - private static final Set FORBIDDEN_REQUEST_EXCEPTIONS = ImmutableSet.of("java.lang.SecurityException", "javax.ws.rs.ForbiddenException"); @@ -100,46 +99,4 @@ public Response post(@Context HugeConfig conf, gremlinOutputHistogram.update(response.getLength()); return transformResponseIfNeeded(response); } - - private static Response transformResponseIfNeeded(Response response) { - MediaType mediaType = response.getMediaType(); - if (mediaType != null) { - // Append charset - assert MediaType.APPLICATION_JSON_TYPE.equals(mediaType); - response.getHeaders().putSingle(HttpHeaders.CONTENT_TYPE, - mediaType.withCharset(CHARSET)); - } - - Response.StatusType status = response.getStatusInfo(); - if (status.getStatusCode() < 400) { - // No need to transform if normal response without error - return response; - } - - if (mediaType == null || !JSON.equals(mediaType.getSubtype())) { - String message = response.readEntity(String.class); - throw new HugeGremlinException(status.getStatusCode(), - ImmutableMap.of("message", message)); - } - - @SuppressWarnings("unchecked") - Map map = response.readEntity(Map.class); - String exClassName = (String) map.get("Exception-Class"); - if (FORBIDDEN_REQUEST_EXCEPTIONS.contains(exClassName)) { - status = Response.Status.FORBIDDEN; - } else if (matchBadRequestException(exClassName)) { - status = Response.Status.BAD_REQUEST; - } - throw new HugeGremlinException(status.getStatusCode(), map); - } - - private static boolean matchBadRequestException(String exClass) { - if (exClass == null) { - return false; - } - if (BAD_REQUEST_EXCEPTIONS.contains(exClass)) { - return true; - } - return BAD_REQUEST_EXCEPTIONS.stream().anyMatch(exClass::startsWith); - } } diff --git a/hugegraph-api/src/main/java/com/baidu/hugegraph/api/gremlin/GremlinQueryAPI.java b/hugegraph-api/src/main/java/com/baidu/hugegraph/api/gremlin/GremlinQueryAPI.java new file mode 100644 index 0000000000..5a072e095a --- /dev/null +++ b/hugegraph-api/src/main/java/com/baidu/hugegraph/api/gremlin/GremlinQueryAPI.java @@ -0,0 +1,90 @@ +package com.baidu.hugegraph.api.gremlin; + +import java.util.Map; +import java.util.Set; + +import com.baidu.hugegraph.api.API; +import com.baidu.hugegraph.config.HugeConfig; +import com.baidu.hugegraph.config.ServerOptions; +import com.baidu.hugegraph.exception.HugeGremlinException; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; + +import jakarta.inject.Provider; +import jakarta.ws.rs.core.Context; +import jakarta.ws.rs.core.HttpHeaders; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.Response; + +public class GremlinQueryAPI extends API { + + private static final Set FORBIDDEN_REQUEST_EXCEPTIONS = + ImmutableSet.of("java.lang.SecurityException", + "jakarta.ws.rs.ForbiddenException"); + private static final Set BAD_REQUEST_EXCEPTIONS = ImmutableSet.of( + "java.lang.IllegalArgumentException", + "java.util.concurrent.TimeoutException", + "groovy.lang.", + "org.codehaus.", + "com.baidu.hugegraph." + ); + + @Context + private Provider configProvider; + + private GremlinClient client; + + public GremlinClient client() { + if (this.client != null) { + return this.client; + } + HugeConfig config = this.configProvider.get(); + String url = config.get(ServerOptions.GREMLIN_SERVER_URL); + int timeout = config.get(ServerOptions.GREMLIN_SERVER_TIMEOUT) * 1000; + int maxRoutes = config.get(ServerOptions.GREMLIN_SERVER_MAX_ROUTE); + this.client = new GremlinClient(url, timeout, maxRoutes, maxRoutes); + return this.client; + } + + protected static Response transformResponseIfNeeded(Response response) { + MediaType mediaType = response.getMediaType(); + if (mediaType != null) { + // Append charset + assert MediaType.APPLICATION_JSON_TYPE.equals(mediaType); + response.getHeaders().putSingle(HttpHeaders.CONTENT_TYPE, + mediaType.withCharset(CHARSET)); + } + + Response.StatusType status = response.getStatusInfo(); + if (status.getStatusCode() < 400) { + // No need to transform if normal response without error + return response; + } + + if (mediaType == null || !JSON.equals(mediaType.getSubtype())) { + String message = response.readEntity(String.class); + throw new HugeGremlinException(status.getStatusCode(), + ImmutableMap.of("message", message)); + } + + @SuppressWarnings("unchecked") + Map map = response.readEntity(Map.class); + String exClassName = (String) map.get("Exception-Class"); + if (FORBIDDEN_REQUEST_EXCEPTIONS.contains(exClassName)) { + status = Response.Status.FORBIDDEN; + } else if (matchBadRequestException(exClassName)) { + status = Response.Status.BAD_REQUEST; + } + throw new HugeGremlinException(status.getStatusCode(), map); + } + + private static boolean matchBadRequestException(String exClass) { + if (exClass == null) { + return false; + } + if (BAD_REQUEST_EXCEPTIONS.contains(exClass)) { + return true; + } + return BAD_REQUEST_EXCEPTIONS.stream().anyMatch(exClass::startsWith); + } +} diff --git a/hugegraph-api/src/main/java/com/baidu/hugegraph/version/ApiVersion.java b/hugegraph-api/src/main/java/com/baidu/hugegraph/version/ApiVersion.java index adf0f58e76..133387bfeb 100644 --- a/hugegraph-api/src/main/java/com/baidu/hugegraph/version/ApiVersion.java +++ b/hugegraph-api/src/main/java/com/baidu/hugegraph/version/ApiVersion.java @@ -118,14 +118,16 @@ public final class ApiVersion { * [0.66] Issue-1567: Support get schema RESTful API * [0.67] Issue-1065: Support dynamically add/remove graph * [0.67] Issue-10: Support adamic-adar & resource-allocation API - * * version 0.13: * [0.67] Issue-11: hugegraph with etcd/pd, * add graphspace, remove auth server + * [0.68] Issue-1763: Support adamic-adar & resource-allocation API + * [0.68] Issue-1763: Support adamic-adar & resource-allocation API + * [0.69] Issue-1748: Support Cypher query RESTful API */ // The second parameter of Version.of() is for IDE running without JAR - public static final Version VERSION = Version.of(ApiVersion.class, "0.68"); + public static final Version VERSION = Version.of(ApiVersion.class, "0.69"); public static final void check() { // Check version of hugegraph-core. Firstly do check from version 0.3 diff --git a/hugegraph-test/src/main/java/com/baidu/hugegraph/api/BaseApiTest.java b/hugegraph-test/src/main/java/com/baidu/hugegraph/api/BaseApiTest.java index 1510a75046..30fddd94f7 100644 --- a/hugegraph-test/src/main/java/com/baidu/hugegraph/api/BaseApiTest.java +++ b/hugegraph-test/src/main/java/com/baidu/hugegraph/api/BaseApiTest.java @@ -60,7 +60,7 @@ public class BaseApiTest { private static final String USERNAME = "admin"; private static final String PASSWORD = "admin"; - private static final String URL_PREFIX = "graphs/" + GRAPH; + protected static final String URL_PREFIX = "graphs/" + GRAPH; private static final String SCHEMA_PKS = "/schema/propertykeys"; private static final String SCHEMA_VLS = "/schema/vertexlabels"; private static final String SCHEMA_ELS = "/schema/edgelabels"; diff --git a/hugegraph-test/src/main/java/com/baidu/hugegraph/api/CypherApiTest.java b/hugegraph-test/src/main/java/com/baidu/hugegraph/api/CypherApiTest.java new file mode 100644 index 0000000000..c2841e9bbb --- /dev/null +++ b/hugegraph-test/src/main/java/com/baidu/hugegraph/api/CypherApiTest.java @@ -0,0 +1,86 @@ +/* + * 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 static com.baidu.hugegraph.testutil.Assert.assertContains; + +import java.util.Map; + +import org.junit.Before; +import org.junit.Test; + +import com.baidu.hugegraph.testutil.Assert; +import com.google.common.collect.ImmutableMap; + +import jakarta.ws.rs.core.Response; + +public class CypherApiTest extends BaseApiTest { + + private static final String path = URL_PREFIX + "/cypher"; + private static final String query = "MATCH (n:person) where n.city ='Beijing' return n"; + private static final String queryResult = "Beijing"; + + @Before + public void prepareSchema() { + BaseApiTest.initPropertyKey(); + BaseApiTest.initVertexLabel(); + BaseApiTest.initEdgeLabel(); + BaseApiTest.initIndexLabel(); + BaseApiTest.initVertex(); + BaseApiTest.initEdge(); + } + + @Test + public void testGet() { + Map params = ImmutableMap.of("cypher", query); + Response r = client().get(path, params); + + this.validStatusAndTextContains(queryResult, r); + } + + @Test + public void testPost() { + this.testCypherQueryAndContains(query, queryResult); + } + + @Test + public void testCreate() { + this.testCypherQueryAndContains("CREATE (n:person { name : 'test', age: 20, city: 'Hefei' }) return n", + "Hefei"); + } + + @Test + public void testRelationQuery() { + String cypher = "MATCH (n:person)-[r:knows]->(friend:person)\n" + + "WHERE n.name = 'marko'\n" + + "RETURN n, friend.name AS friend"; + this.testCypherQueryAndContains(cypher, "friend"); + } + + private void testCypherQueryAndContains(String cypher, String containsText) { + Response r = client().post(path, cypher); + this.validStatusAndTextContains(containsText, r); + } + + private void validStatusAndTextContains(String value, Response r) { + String content = assertResponseStatus(200, r); + assertContains(value, content); + } +} From eac47ac04c9079dd68cd22a04c445caebd0c2670 Mon Sep 17 00:00:00 2001 From: YangJiaqi Date: Fri, 13 May 2022 17:00:10 +0800 Subject: [PATCH 2/5] fix checkstyle : CypherApiTest (#1877) --- .../baidu/hugegraph/api/CypherApiTest.java | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/hugegraph-test/src/main/java/com/baidu/hugegraph/api/CypherApiTest.java b/hugegraph-test/src/main/java/com/baidu/hugegraph/api/CypherApiTest.java index c2841e9bbb..da849a4e98 100644 --- a/hugegraph-test/src/main/java/com/baidu/hugegraph/api/CypherApiTest.java +++ b/hugegraph-test/src/main/java/com/baidu/hugegraph/api/CypherApiTest.java @@ -26,16 +26,15 @@ import org.junit.Before; import org.junit.Test; -import com.baidu.hugegraph.testutil.Assert; import com.google.common.collect.ImmutableMap; import jakarta.ws.rs.core.Response; public class CypherApiTest extends BaseApiTest { - private static final String path = URL_PREFIX + "/cypher"; - private static final String query = "MATCH (n:person) where n.city ='Beijing' return n"; - private static final String queryResult = "Beijing"; + private static final String PATH = URL_PREFIX + "/cypher"; + private static final String QUERY = "MATCH (n:person) where n.city ='Beijing' return n"; + private static final String QUERY_RESULT = "Beijing"; @Before public void prepareSchema() { @@ -49,20 +48,21 @@ public void prepareSchema() { @Test public void testGet() { - Map params = ImmutableMap.of("cypher", query); - Response r = client().get(path, params); + Map params = ImmutableMap.of("cypher", QUERY); + Response r = client().get(PATH, params); - this.validStatusAndTextContains(queryResult, r); + this.validStatusAndTextContains(QUERY_RESULT, r); } @Test public void testPost() { - this.testCypherQueryAndContains(query, queryResult); + this.testCypherQueryAndContains(QUERY, QUERY_RESULT); } @Test public void testCreate() { - this.testCypherQueryAndContains("CREATE (n:person { name : 'test', age: 20, city: 'Hefei' }) return n", + this.testCypherQueryAndContains("CREATE (n:person { name : 'test', " + + "age: 20, city: 'Hefei' }) return n", "Hefei"); } @@ -75,7 +75,7 @@ public void testRelationQuery() { } private void testCypherQueryAndContains(String cypher, String containsText) { - Response r = client().post(path, cypher); + Response r = client().post(PATH, cypher); this.validStatusAndTextContains(containsText, r); } From 2b5c130ab49c64a502152a5180bad96987617146 Mon Sep 17 00:00:00 2001 From: xhtian95 Date: Thu, 16 Jun 2022 15:08:38 +0800 Subject: [PATCH 3/5] modify cypherapi to support query under different graphspaces --- hugegraph-api/pom.xml | 1 + .../hugegraph/api/gremlin/CypherAPI.java | 83 ++++++++++--------- .../api/gremlin/GremlinQueryAPI.java | 10 +-- .../baidu/hugegraph/api/CypherApiTest.java | 4 +- 4 files changed, 53 insertions(+), 45 deletions(-) diff --git a/hugegraph-api/pom.xml b/hugegraph-api/pom.xml index fab02997c6..92ffac9f40 100644 --- a/hugegraph-api/pom.xml +++ b/hugegraph-api/pom.xml @@ -108,6 +108,7 @@ org.opencypher.gremlin translation 1.0.4 + compile diff --git a/hugegraph-api/src/main/java/com/baidu/hugegraph/api/gremlin/CypherAPI.java b/hugegraph-api/src/main/java/com/baidu/hugegraph/api/gremlin/CypherAPI.java index f85ae03785..d805aadb54 100644 --- a/hugegraph-api/src/main/java/com/baidu/hugegraph/api/gremlin/CypherAPI.java +++ b/hugegraph-api/src/main/java/com/baidu/hugegraph/api/gremlin/CypherAPI.java @@ -8,19 +8,19 @@ import com.baidu.hugegraph.util.Log; import com.codahale.metrics.annotation.Timed; -import jakarta.inject.Singleton; -import jakarta.ws.rs.Consumes; -import jakarta.ws.rs.GET; -import jakarta.ws.rs.POST; -import jakarta.ws.rs.Path; -import jakarta.ws.rs.PathParam; -import jakarta.ws.rs.Produces; -import jakarta.ws.rs.QueryParam; -import jakarta.ws.rs.core.Context; -import jakarta.ws.rs.core.HttpHeaders; -import jakarta.ws.rs.core.Response; - -@Path("graphs/{graph}/cypher") +import javax.inject.Singleton; +import javax.ws.rs.Consumes; +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 javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.Response; + +@Path("graphspaces/{graphspace}/graphs/{graph}/cypher") @Singleton public class CypherAPI extends GremlinQueryAPI { @@ -31,12 +31,13 @@ public class CypherAPI extends GremlinQueryAPI { @Timed @CompressInterceptor.Compress(buffer = (1024 * 40)) @Produces(APPLICATION_JSON_WITH_CHARSET) - public Response query(@PathParam("graph") String graph, - @Context HttpHeaders headers, - @QueryParam("cypher") String cypher) { - LOG.debug("Graph [{}] query by cypher: {}", graph, cypher); + public Response query(@Context HttpHeaders headers, + @PathParam("graphspace") String graphspace, + @PathParam("graph") String graph, + @QueryParam("cypher") String cypher + ) { - return this.queryByCypher(graph, headers, cypher); + return this.queryByCypher(headers, graphspace, graph, cypher); } @POST @@ -44,41 +45,45 @@ public Response query(@PathParam("graph") String graph, @CompressInterceptor.Compress @Consumes(APPLICATION_JSON) @Produces(APPLICATION_JSON_WITH_CHARSET) - public Response post(@PathParam("graph") String graph, - @Context HttpHeaders headers, + public Response post(@Context HttpHeaders headers, + @PathParam("graphspace") String graphspace, + @PathParam("graph") String graph, String cypher) { - LOG.debug("Graph [{}] query by cypher: {}", graph, cypher); - return this.queryByCypher(graph, headers, cypher); + + return this.queryByCypher(headers, graphspace, graph, cypher); } - private Response queryByCypher(String graph, - HttpHeaders headers, - String cypher) { - E.checkArgument(cypher != null && !cypher.isEmpty(), - "The cypher parameter can't be null or empty"); + private Response queryByCypher(HttpHeaders headers, String graphspace, + String graph, String cypher) { - String gremlin = this.translateCpyher2Gremlin(graph, cypher); + E.checkArgument(graphspace != null && !graphspace.isEmpty(), + "The graphspace parameter can't be null or empty"); + E.checkArgument(graph != null && !graph.isEmpty(), + "The graph parameter can't be null or empty"); + E.checkArgument(cypher != null && !cypher.isEmpty(), + "The cypher parameter can't be null or empty"); + String gremlin = this.translateCpyher2Gremlin(cypher); LOG.debug("translated gremlin is {}", gremlin); - String auth = headers.getHeaderString(HttpHeaders.AUTHORIZATION); - String request = "{" - + "\"gremlin\":\"" + gremlin + "\"," - + "\"bindings\":{}," - + "\"language\":\"gremlin-groovy\"," - + "\"aliases\":{\"g\":\"__g_" + graph + "\"}}"; - - Response response = this.client().doPostRequest(auth, request); + String graphInfo = graphspace + "-" + graph; + String gremlinQuery = "{" + + "\"gremlin\":\"" + gremlin + "\"," + + "\"bindings\":{}," + + "\"language\":\"gremlin-groovy\"," + + "\"aliases\":{\"graph\":" + "\"" + graphInfo + "\"" + + ", \"g\":\"__g_" + graphInfo + "\"" + "}}"; + Response response = this.client().doPostRequest(auth, gremlinQuery); return transformResponseIfNeeded(response); } - private String translateCpyher2Gremlin(String graph, String cypher) { + private String translateCpyher2Gremlin(String cypher) { TranslationFacade translator = new TranslationFacade(); String gremlin = translator.toGremlinGroovy(cypher); - gremlin = this.buildQueryableGremlin(graph, gremlin); + gremlin = this.buildQueryableGremlin(gremlin); return gremlin; } - private String buildQueryableGremlin(String graph, String gremlin) { + private String buildQueryableGremlin(String gremlin) { /* * `CREATE (a:person { name : 'test', age: 20) return a` * would be translated to: diff --git a/hugegraph-api/src/main/java/com/baidu/hugegraph/api/gremlin/GremlinQueryAPI.java b/hugegraph-api/src/main/java/com/baidu/hugegraph/api/gremlin/GremlinQueryAPI.java index 5a072e095a..87ca2ae332 100644 --- a/hugegraph-api/src/main/java/com/baidu/hugegraph/api/gremlin/GremlinQueryAPI.java +++ b/hugegraph-api/src/main/java/com/baidu/hugegraph/api/gremlin/GremlinQueryAPI.java @@ -10,11 +10,11 @@ import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; -import jakarta.inject.Provider; -import jakarta.ws.rs.core.Context; -import jakarta.ws.rs.core.HttpHeaders; -import jakarta.ws.rs.core.MediaType; -import jakarta.ws.rs.core.Response; +import javax.inject.Provider; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; public class GremlinQueryAPI extends API { diff --git a/hugegraph-test/src/main/java/com/baidu/hugegraph/api/CypherApiTest.java b/hugegraph-test/src/main/java/com/baidu/hugegraph/api/CypherApiTest.java index da849a4e98..229eeff5e4 100644 --- a/hugegraph-test/src/main/java/com/baidu/hugegraph/api/CypherApiTest.java +++ b/hugegraph-test/src/main/java/com/baidu/hugegraph/api/CypherApiTest.java @@ -23,12 +23,13 @@ import java.util.Map; +import groovy.grape.GrapeIvy; import org.junit.Before; import org.junit.Test; import com.google.common.collect.ImmutableMap; -import jakarta.ws.rs.core.Response; +import javax.ws.rs.core.Response; public class CypherApiTest extends BaseApiTest { @@ -44,6 +45,7 @@ public void prepareSchema() { BaseApiTest.initIndexLabel(); BaseApiTest.initVertex(); BaseApiTest.initEdge(); + System.out.println("初始化完毕!"); } @Test From 11c6e7fd7b03ceffa43d2d008cc9f0e69546eea0 Mon Sep 17 00:00:00 2001 From: xhtian95 Date: Thu, 16 Jun 2022 18:42:51 +0800 Subject: [PATCH 4/5] add cypherApiTest to ApiTestSuite.java --- .../java/com/baidu/hugegraph/api/gremlin/CypherAPI.java | 7 +++---- .../main/java/com/baidu/hugegraph/version/ApiVersion.java | 1 - .../main/java/com/baidu/hugegraph/api/ApiTestSuite.java | 3 ++- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/hugegraph-api/src/main/java/com/baidu/hugegraph/api/gremlin/CypherAPI.java b/hugegraph-api/src/main/java/com/baidu/hugegraph/api/gremlin/CypherAPI.java index d805aadb54..6af2b0cf53 100644 --- a/hugegraph-api/src/main/java/com/baidu/hugegraph/api/gremlin/CypherAPI.java +++ b/hugegraph-api/src/main/java/com/baidu/hugegraph/api/gremlin/CypherAPI.java @@ -34,8 +34,7 @@ public class CypherAPI extends GremlinQueryAPI { public Response query(@Context HttpHeaders headers, @PathParam("graphspace") String graphspace, @PathParam("graph") String graph, - @QueryParam("cypher") String cypher - ) { + @QueryParam("cypher") String cypher) { return this.queryByCypher(headers, graphspace, graph, cypher); } @@ -62,7 +61,7 @@ private Response queryByCypher(HttpHeaders headers, String graphspace, "The graph parameter can't be null or empty"); E.checkArgument(cypher != null && !cypher.isEmpty(), "The cypher parameter can't be null or empty"); - String gremlin = this.translateCpyher2Gremlin(cypher); + String gremlin = this.translateCypher2Gremlin(cypher); LOG.debug("translated gremlin is {}", gremlin); String auth = headers.getHeaderString(HttpHeaders.AUTHORIZATION); String graphInfo = graphspace + "-" + graph; @@ -76,7 +75,7 @@ private Response queryByCypher(HttpHeaders headers, String graphspace, return transformResponseIfNeeded(response); } - private String translateCpyher2Gremlin(String cypher) { + private String translateCypher2Gremlin(String cypher) { TranslationFacade translator = new TranslationFacade(); String gremlin = translator.toGremlinGroovy(cypher); gremlin = this.buildQueryableGremlin(gremlin); diff --git a/hugegraph-api/src/main/java/com/baidu/hugegraph/version/ApiVersion.java b/hugegraph-api/src/main/java/com/baidu/hugegraph/version/ApiVersion.java index 133387bfeb..5d10679c0b 100644 --- a/hugegraph-api/src/main/java/com/baidu/hugegraph/version/ApiVersion.java +++ b/hugegraph-api/src/main/java/com/baidu/hugegraph/version/ApiVersion.java @@ -122,7 +122,6 @@ public final class ApiVersion { * [0.67] Issue-11: hugegraph with etcd/pd, * add graphspace, remove auth server * [0.68] Issue-1763: Support adamic-adar & resource-allocation API - * [0.68] Issue-1763: Support adamic-adar & resource-allocation API * [0.69] Issue-1748: Support Cypher query RESTful API */ diff --git a/hugegraph-test/src/main/java/com/baidu/hugegraph/api/ApiTestSuite.java b/hugegraph-test/src/main/java/com/baidu/hugegraph/api/ApiTestSuite.java index a601bdb7a8..066aaa2c79 100644 --- a/hugegraph-test/src/main/java/com/baidu/hugegraph/api/ApiTestSuite.java +++ b/hugegraph-test/src/main/java/com/baidu/hugegraph/api/ApiTestSuite.java @@ -40,7 +40,8 @@ MetricsApiTest.class, UserApiTest.class, LoginApiTest.class, - TraversersApiTestSuite.class + TraversersApiTestSuite.class, + CypherApiTest.class }) public class ApiTestSuite { From 5e5a811636168d40fa0241afbd058bfa378cbb16 Mon Sep 17 00:00:00 2001 From: xhtian95 Date: Fri, 17 Jun 2022 14:24:24 +0800 Subject: [PATCH 5/5] delete a redundant print statement in CypherApiTest.java --- .../src/main/java/com/baidu/hugegraph/api/CypherApiTest.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/hugegraph-test/src/main/java/com/baidu/hugegraph/api/CypherApiTest.java b/hugegraph-test/src/main/java/com/baidu/hugegraph/api/CypherApiTest.java index 229eeff5e4..765a6bd074 100644 --- a/hugegraph-test/src/main/java/com/baidu/hugegraph/api/CypherApiTest.java +++ b/hugegraph-test/src/main/java/com/baidu/hugegraph/api/CypherApiTest.java @@ -23,7 +23,6 @@ import java.util.Map; -import groovy.grape.GrapeIvy; import org.junit.Before; import org.junit.Test; @@ -45,7 +44,6 @@ public void prepareSchema() { BaseApiTest.initIndexLabel(); BaseApiTest.initVertex(); BaseApiTest.initEdge(); - System.out.println("初始化完毕!"); } @Test