diff --git a/geaflow/geaflow-dsl/geaflow-dsl-plan/src/main/java/org/apache/geaflow/dsl/schema/function/BuildInSqlFunctionTable.java b/geaflow/geaflow-dsl/geaflow-dsl-plan/src/main/java/org/apache/geaflow/dsl/schema/function/BuildInSqlFunctionTable.java index 9656d9299..28b3dd7f3 100644 --- a/geaflow/geaflow-dsl/geaflow-dsl-plan/src/main/java/org/apache/geaflow/dsl/schema/function/BuildInSqlFunctionTable.java +++ b/geaflow/geaflow-dsl/geaflow-dsl-plan/src/main/java/org/apache/geaflow/dsl/schema/function/BuildInSqlFunctionTable.java @@ -37,6 +37,7 @@ import org.apache.geaflow.dsl.udf.graph.AllSourceShortestPath; import org.apache.geaflow.dsl.udf.graph.ClosenessCentrality; import org.apache.geaflow.dsl.udf.graph.ClusterCoefficient; +import org.apache.geaflow.dsl.udf.graph.Degree; import org.apache.geaflow.dsl.udf.graph.CommonNeighbors; import org.apache.geaflow.dsl.udf.graph.ConnectedComponents; import org.apache.geaflow.dsl.udf.graph.IncKHopAlgorithm; @@ -251,6 +252,7 @@ public class BuildInSqlFunctionTable extends ListSqlOperatorTable { .add(GeaFlowFunction.of(LabelPropagation.class)) .add(GeaFlowFunction.of(ConnectedComponents.class)) .add(GeaFlowFunction.of(Louvain.class)) + .add(GeaFlowFunction.of(Degree.class)) .build(); public BuildInSqlFunctionTable(GQLJavaTypeFactory typeFactory) { diff --git a/geaflow/geaflow-dsl/geaflow-dsl-plan/src/main/java/org/apache/geaflow/dsl/udf/graph/Degree.java b/geaflow/geaflow-dsl/geaflow-dsl-plan/src/main/java/org/apache/geaflow/dsl/udf/graph/Degree.java new file mode 100644 index 000000000..608ca939b --- /dev/null +++ b/geaflow/geaflow-dsl/geaflow-dsl-plan/src/main/java/org/apache/geaflow/dsl/udf/graph/Degree.java @@ -0,0 +1,77 @@ +/* + * 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 org.apache.geaflow.dsl.udf.graph; + +import java.util.Iterator; +import java.util.List; +import java.util.Optional; +import org.apache.geaflow.common.type.primitive.IntegerType; +import org.apache.geaflow.dsl.common.algo.AlgorithmRuntimeContext; +import org.apache.geaflow.dsl.common.algo.AlgorithmUserFunction; +import org.apache.geaflow.dsl.common.data.Row; +import org.apache.geaflow.dsl.common.data.RowEdge; +import org.apache.geaflow.dsl.common.data.RowVertex; +import org.apache.geaflow.dsl.common.data.impl.ObjectRow; +import org.apache.geaflow.dsl.common.function.Description; +import org.apache.geaflow.dsl.common.types.GraphSchema; +import org.apache.geaflow.dsl.common.types.StructType; +import org.apache.geaflow.dsl.common.types.TableField; +import org.apache.geaflow.model.graph.edge.EdgeDirection; + +@Description(name = "degree", description = "built-in udga for Degree") +public class Degree implements AlgorithmUserFunction { + + private AlgorithmRuntimeContext context; + + @Override + public void init(AlgorithmRuntimeContext context, Object[] params) { + this.context = context; + if (params.length > 0) { + throw new IllegalArgumentException( + "Degree does not support any arguments, usage: func()"); + } + } + + @Override + public void process(RowVertex vertex, Optional updatedValues, Iterator messages) { + updatedValues.ifPresent(vertex::setValue); + int inDegree = this.context.loadEdges(EdgeDirection.IN).size(); + int outDegree = this.context.loadEdges(EdgeDirection.OUT).size(); + context.updateVertexValue(ObjectRow.create(inDegree, outDegree)); + } + + @Override + public void finish(RowVertex graphVertex, Optional updatedValues) { + updatedValues.ifPresent(graphVertex::setValue); + int inDegree = (int) graphVertex.getValue().getField(0, IntegerType.INSTANCE); + int outDegree = (int) graphVertex.getValue().getField(1, IntegerType.INSTANCE); + context.take(ObjectRow.create(graphVertex.getId(), inDegree, outDegree)); + } + + @Override + public StructType getOutputType(GraphSchema graphSchema) { + return new StructType( + new TableField("id", graphSchema.getIdType(), false), + new TableField("in_degree", IntegerType.INSTANCE, false), + new TableField("out_degree", IntegerType.INSTANCE, false) + ); + } + +} \ No newline at end of file diff --git a/geaflow/geaflow-dsl/geaflow-dsl-runtime/src/test/java/org/apache/geaflow/dsl/runtime/query/GQLAlgorithmTest.java b/geaflow/geaflow-dsl/geaflow-dsl-runtime/src/test/java/org/apache/geaflow/dsl/runtime/query/GQLAlgorithmTest.java index 673f4ef81..3efc4c642 100644 --- a/geaflow/geaflow-dsl/geaflow-dsl-runtime/src/test/java/org/apache/geaflow/dsl/runtime/query/GQLAlgorithmTest.java +++ b/geaflow/geaflow-dsl/geaflow-dsl-runtime/src/test/java/org/apache/geaflow/dsl/runtime/query/GQLAlgorithmTest.java @@ -363,6 +363,16 @@ public void testAlgorithmJaccardSimilarity() throws Exception { .checkSinkResult(); } + @Test + public void testAlgorithmDegree() throws Exception { + QueryTester + .build() + .withGraphDefine("/query/modern_graph.sql") + .withQueryPath("/query/gql_algorithm_degree.sql") + .execute() + .checkSinkResult(); + } + @Test public void testEdgeIterator() throws Exception { QueryTester diff --git a/geaflow/geaflow-dsl/geaflow-dsl-runtime/src/test/resources/expect/gql_algorithm_degree.txt b/geaflow/geaflow-dsl/geaflow-dsl-runtime/src/test/resources/expect/gql_algorithm_degree.txt new file mode 100644 index 000000000..3e1e2d7a6 --- /dev/null +++ b/geaflow/geaflow-dsl/geaflow-dsl-runtime/src/test/resources/expect/gql_algorithm_degree.txt @@ -0,0 +1,6 @@ +1,0,3 +2,1,0 +3,3,0 +4,1,2 +5,1,0 +6,0,1 \ No newline at end of file diff --git a/geaflow/geaflow-dsl/geaflow-dsl-runtime/src/test/resources/query/gql_algorithm_degree.sql b/geaflow/geaflow-dsl/geaflow-dsl-runtime/src/test/resources/query/gql_algorithm_degree.sql new file mode 100644 index 000000000..70f2e6d75 --- /dev/null +++ b/geaflow/geaflow-dsl/geaflow-dsl-runtime/src/test/resources/query/gql_algorithm_degree.sql @@ -0,0 +1,28 @@ +/* + * 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. + */ + +CREATE TABLE result_tb (vid int, in_degree int, out_degree int) + WITH (type='file', geaflow.dsl.file.path='${target}'); + +USE GRAPH modern; + +INSERT INTO result_tb +CALL degree() YIELD (vid, in_degree, out_degree) +RETURN cast (vid as int), in_degree, out_degree +; \ No newline at end of file