From 824ba4e5e9ae9fd290115c344d3ea9b60e5e7178 Mon Sep 17 00:00:00 2001 From: shizhichao Date: Mon, 23 Sep 2024 15:37:50 +0800 Subject: [PATCH 1/6] three builtin_app --- flex/engines/graph_db/app/builtin/TVSP.cc | 228 ++++++++++++++++++ flex/engines/graph_db/app/builtin/TVSP.h | 50 ++++ .../app/builtin/k_degree_neighbors.cc | 116 +++++++++ .../graph_db/app/builtin/k_degree_neighbors.h | 43 ++++ flex/engines/graph_db/app/builtin/pagerank.cc | 134 ++++++++++ flex/engines/graph_db/app/builtin/pagerank.h | 52 ++++ flex/engines/graph_db/database/graph_db.cc | 10 + flex/storages/metadata/graph_meta_store.cc | 60 +++++ 8 files changed, 693 insertions(+) create mode 100644 flex/engines/graph_db/app/builtin/TVSP.cc create mode 100644 flex/engines/graph_db/app/builtin/TVSP.h create mode 100644 flex/engines/graph_db/app/builtin/k_degree_neighbors.cc create mode 100644 flex/engines/graph_db/app/builtin/k_degree_neighbors.h create mode 100644 flex/engines/graph_db/app/builtin/pagerank.cc create mode 100644 flex/engines/graph_db/app/builtin/pagerank.h diff --git a/flex/engines/graph_db/app/builtin/TVSP.cc b/flex/engines/graph_db/app/builtin/TVSP.cc new file mode 100644 index 000000000000..17efb1af639f --- /dev/null +++ b/flex/engines/graph_db/app/builtin/TVSP.cc @@ -0,0 +1,228 @@ +/** Copyright 2020 Alibaba Group Holding Limited. + * + * Licensed 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. + */ +#include "flex/engines/graph_db/app/builtin/TVSP.h" + +namespace gs { + +bool TVSP::DoQuery(GraphDBSession& sess, Decoder& input,Encoder& output) { + ReadTransaction txn = sess.GetReadTransaction(); + if (input.empty()) { + return false; + } + Schema schema_ = txn.schema(); + std::string label_name1{input.get_string()}; + vid_t vid1=input.get_int(); + std::string label_name2{input.get_string()}; + vid_t vid2=input.get_int(); + std::string label_name3{input.get_string()}; + vid_t vid3=input.get_int(); + + if(!schema_.has_vertex_label(label_name1)||!schema_.has_vertex_label(label_name2) + ||!schema_.has_vertex_label(label_name3)){ + output.put_string_view("The requested label doesn't exits."); + return false; // The requested label doesn't exits. + } + label_t label_v1=schema_.get_vertex_label_id(label_name1); + label_t label_v2=schema_.get_vertex_label_id(label_name2); + label_t label_v3=schema_.get_vertex_label_id(label_name3); + vid_t index_v1{}; + vid_t index_v2{}; + vid_t index_v3{}; + if(!txn.GetVertexIndex(label_v1, (int64_t)vid1, index_v1)|| + !txn.GetVertexIndex(label_v2, (int64_t)vid2, index_v2)|| + !txn.GetVertexIndex(label_v3, (int64_t)vid3, index_v3)) + { + output.put_string_view("get index fail."); + return false; + } + + uint vertex_num = 0 ; + for(label_t i = 0 ; i v1v2result_; + std::vector v2v3result_; + std::vector v1v3result_; + + bool find_flag = true; + if(!ShortestPath(txn,label_v1,index_v1,label_v2,index_v2,v1v2result_,vertex_num)){ + find_flag=false; + } + if(find_flag&&!ShortestPath(txn,label_v2,index_v2,label_v3,index_v3,v2v3result_,vertex_num)){ + find_flag=false; + } + if(find_flag&&!ShortestPath(txn,label_v1,index_v1,label_v3,index_v3,v1v3result_,vertex_num)){ + find_flag=false; + } + std::string result_path = ""; + if(find_flag){ + //选择最短的两条路径进行连接 + std::vector TSP = ConnectPath(v1v2result_,v2v3result_,v1v3result_); + for(auto it = TSP.begin(); it != TSP.end(); ++it){ + if (std::next(it) != TSP.end()) { + result_path += std::to_string(*it)+"--"; // 如果当前元素不是最后一个,则添加空格 + } + else{ + result_path += std::to_string(*it); + } + } + } + else{ + result_path="no path find!"; + } + + // 向CollectiveResults中添加多个Results对象 + results::CollectiveResults results; + auto result = results.add_results(); + result->mutable_record() + ->add_columns() + ->mutable_entry() + ->mutable_element() + ->mutable_object() + ->set_str(result_path); + + output.put_string_view(results.SerializeAsString()); + txn.Commit(); + return true; +} + +bool TVSP::ShortestPath(const gs::ReadTransaction& txn, label_t v1_l,vid_t v1_index,label_t v2_l,vid_t v2_index,std::vector &result_, uint vertex_num){ + Schema schema_ = txn.schema(); + int vertex_size_ = (int)schema_.vertex_label_num(); + int edge_size_ = (int)schema_.edge_label_num(); + + std::vector visited(vertex_num+1, false); + std::unordered_map parent; + std::vector nei_label_; + std::vector nei_index_; + int64_t v1_id = txn.GetVertexId(v1_l, v1_index).AsInt64(); + int64_t v2_id = txn.GetVertexId(v2_l, v2_index).AsInt64(); + + // std::cout<<"v1: "< next_nei_labels_; + std::vector next_nei_indexs_; + bool find = false; + while(!nei_label_.empty()&&!find) { + for(long unsigned int i = 0 ; i< nei_index_.size();i++){ + for(int j = 0 ; j TVSP::ConnectPath(std::vector &path1,std::vector &path2, + std::vector &path3){ + std::vector TSP; + int v1v2size = (int)path1.size(); + int v2v3size = (int)path2.size(); + int v1v3size = (int)path3.size(); + if(v1v2size<=v2v3size&&v1v3size<=v2v3size){ + for(int i =v1v2size-1;i>=0;i--){ + TSP.push_back(path1[i]); + } + for(int i = 1;i=0;i--){ + TSP.push_back(path3[i]); + } + } + return TSP; +} +AppWrapper TVSPFactory::CreateApp(const GraphDB& db) { + return AppWrapper(new TVSP(), NULL); +} +} // namespace gs diff --git a/flex/engines/graph_db/app/builtin/TVSP.h b/flex/engines/graph_db/app/builtin/TVSP.h new file mode 100644 index 000000000000..0c43c2c378d9 --- /dev/null +++ b/flex/engines/graph_db/app/builtin/TVSP.h @@ -0,0 +1,50 @@ +/** Copyright 2020 Alibaba Group Holding Limited. + * + * Licensed 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. + */ + +#ifndef ENGINES_GRAPH_DB_APP_BUILDIN_TVSP_H_ +#define ENGINES_GRAPH_DB_APP_BUILDIN_TVSP_H_ +#include "flex/engines/graph_db/database/graph_db_session.h" +#include "flex/engines/hqps_db/app/interactive_app_base.h" + +namespace gs { +// A simple app to count the number of vertices of a given label. +class TVSP : public CypherInternalPbWriteAppBase { + private: +// std::string label_name1; +// int32_t vid1; +// std::string label_name2; +// int32_t vid2; +// std::string label_name3; +// int32_t vid3; + + public: + TVSP() {} + bool DoQuery(GraphDBSession& sess, Decoder& input, Encoder& output) override; + bool ShortestPath(const gs::ReadTransaction& txn, label_t v1_l,vid_t v1_index,label_t v2_l,vid_t v2_index,std::vector &result_, uint vertex_num); + std::vector ConnectPath(std::vector &path1,std::vector &path2,std::vector &path3); + +}; + +class TVSPFactory : public AppFactoryBase { + public: + TVSPFactory() = default; + ~TVSPFactory() = default; + + AppWrapper CreateApp(const GraphDB& db) override; +}; + +} // namespace gs + +#endif // ENGINES_GRAPH_DB_APP_BUILDIN_TVSP_H_ \ No newline at end of file diff --git a/flex/engines/graph_db/app/builtin/k_degree_neighbors.cc b/flex/engines/graph_db/app/builtin/k_degree_neighbors.cc new file mode 100644 index 000000000000..f5fa5deaeeb5 --- /dev/null +++ b/flex/engines/graph_db/app/builtin/k_degree_neighbors.cc @@ -0,0 +1,116 @@ +/** Copyright 2020 Alibaba Group Holding Limited. + * + * Licensed 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. + */ +#include "flex/engines/graph_db/app/builtin/k_degree_neighbors.h" + +namespace gs { + +bool KNeighbors::DoQuery(GraphDBSession& sess, Decoder& input, + Encoder& output) { + // 创建一个CollectiveResults对象 + auto txn = sess.GetReadTransaction(); + Schema schema_ = txn.schema(); + if (input.empty()) { + return false; + } + this->vertex_id_=input.get_int(); + std::string label_name { input.get_string()}; + this->k=input.get_int(); + + if(k<=0) { + output.put_string_view("k must be greater than 0."); + return false; + } + if(!schema_.has_vertex_label(label_name)){ + output.put_string_view("The requested label doesn't exits."); + return false; // The requested label doesn't exits. + } + this->vertex_label_=schema_.get_vertex_label_id(label_name); + + + std::set k_neighbors; + + int vertex_size_ = (int)schema_.vertex_label_num(); + int edge_size_ = (int)schema_.edge_label_num(); + + std::vector nei_index_; + std::vector nei_label_; + std::vector next_nei_indexs_; + std::vector next_nei_label_; + + nei_label_.push_back(vertex_label_); + vid_t vertex_index{}; + if(!txn.GetVertexIndex(vertex_label_, (int64_t)vertex_id_, vertex_index)){ + output.put_string_view("get index fail."); + return false; + } + nei_index_.push_back(vertex_index); + //层次遍历得到k跳邻居 + while(!nei_index_.empty() && k > 0) { + for(long unsigned int i = 0 ; imutable_record() + ->add_columns() + ->mutable_entry() + ->mutable_element() + ->mutable_object() + ->set_str(res); + output.put_string_view(results.SerializeAsString()); + txn.Commit(); + return true; +} + +AppWrapper KNeighborsFactory::CreateApp(const GraphDB& db) { + return AppWrapper(new KNeighbors(), NULL); +} +} // namespace gs diff --git a/flex/engines/graph_db/app/builtin/k_degree_neighbors.h b/flex/engines/graph_db/app/builtin/k_degree_neighbors.h new file mode 100644 index 000000000000..543c4212ddb8 --- /dev/null +++ b/flex/engines/graph_db/app/builtin/k_degree_neighbors.h @@ -0,0 +1,43 @@ +/** Copyright 2020 Alibaba Group Holding Limited. + * + * Licensed 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. + */ + +#ifndef ENGINES_GRAPH_DB_APP_BUILDIN_K_DEGREE_NEI_ +#define ENGINES_GRAPH_DB_APP_BUILDIN_K_DEGREE_NEI_ +#include "flex/engines/graph_db/database/graph_db_session.h" +#include "flex/engines/hqps_db/app/interactive_app_base.h" + +namespace gs { +// A simple app to count the number of vertices of a given label. +class KNeighbors : public CypherInternalPbWriteAppBase { + private: + vid_t vertex_id_; + label_t vertex_label_; + int32_t k; + public: + KNeighbors() {} + bool DoQuery(GraphDBSession& sess, Decoder& input, Encoder& output) override; +}; + +class KNeighborsFactory : public AppFactoryBase { + public: + KNeighborsFactory() = default; + ~KNeighborsFactory() = default; + + AppWrapper CreateApp(const GraphDB& db) override; +}; + +} // namespace gs + +#endif // ENGINES_GRAPH_DB_APP_BUILDIN_COUNT_VERTICES_H_ \ No newline at end of file diff --git a/flex/engines/graph_db/app/builtin/pagerank.cc b/flex/engines/graph_db/app/builtin/pagerank.cc new file mode 100644 index 000000000000..d32e6cdbff9a --- /dev/null +++ b/flex/engines/graph_db/app/builtin/pagerank.cc @@ -0,0 +1,134 @@ +/** Copyright 2020 Alibaba Group Holding Limited. + * + * Licensed 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. + */ +#include "flex/engines/graph_db/app/builtin/pagerank.h" + +namespace gs { + + +bool PageRank::DoQuery(GraphDBSession& sess, Decoder& input, + Encoder& output) { + // First get the read transaction. + auto txn = sess.GetReadTransaction(); + // We expect one param of type string from decoder. + if (input.empty()) { + return false; + } + std::string vertex_label{input.get_string()}; + std::string edge_label{input.get_string()}; + + if(!input.empty()) { + damping_factor_ = input.get_double(); + max_iterations_ = input.get_int(); + epsilon_ = input.get_double(); + } + + vertex_label_id_ = sess.schema().get_vertex_label_id(vertex_label); + edge_label_id_ = sess.schema().get_edge_label_id(edge_label); + + // 统计顶点数量 + auto num_vertices = txn.GetVertexNum(vertex_label_id_); + + // 初始化每个顶点的PageRank值为 1.0 / num_vertices + std::unordered_map pagerank; + std::unordered_map new_pagerank; + + auto vertex_iter = txn.GetVertexIterator(vertex_label_id_); + + while (vertex_iter.IsValid()) { + vid_t vid = vertex_iter.GetIndex(); + pagerank[vid] = 1.0 / num_vertices; + new_pagerank[vid] = 0.0; + vertex_iter.Next(); + } + + // 获取点的出度 + std::unordered_map outdegree; + + // 开始迭代计算PageRank值 + for (int iter = 0; iter < max_iterations_; ++iter) { + // 初始化新的PageRank值 + for (auto& kv : new_pagerank) { + kv.second = 0.0; + } + + // 遍历所有顶点 + auto vertex_iter = txn.GetVertexIterator(vertex_label_id_); + while (vertex_iter.IsValid()) { + vid_t v = vertex_iter.GetIndex(); + + // 遍历所有出边并累加其PageRank贡献值 + double sum = 0.0; + auto edges = txn.GetInEdgeIterator(vertex_label_id_, v, vertex_label_id_, edge_label_id_); + while(edges.IsValid()){ + auto neighbor = edges.GetNeighbor(); + if(outdegree[neighbor] == 0){ + auto out_edges = txn.GetOutEdgeIterator(vertex_label_id_, neighbor, vertex_label_id_, edge_label_id_); + while(out_edges.IsValid()){ + outdegree[neighbor]++; + out_edges.Next(); + } + } + sum += pagerank[neighbor] / outdegree[neighbor]; + edges.Next(); + } + + // 计算新的PageRank值 + new_pagerank[v] = damping_factor_ * sum + (1.0 - damping_factor_) / num_vertices; + vertex_iter.Next(); + } + + // 检查收敛 + double diff = 0.0; + for (const auto& kv : pagerank) { + diff += std::abs(new_pagerank[kv.first] - kv.second); + } + + // 如果收敛,则停止迭代 + if (diff < epsilon_) { + break; + } + + // 交换pagerank与new_pagerank的内容 + std::swap(pagerank, new_pagerank); + } + + std::ostringstream output_stream; + for(auto kv : pagerank) { + auto id =txn.GetVertexId(vertex_label_id_, kv.first).AsInt64(); + // output.put_int(static_cast(id)); + // output.put_double(kv.second); + output_stream << "vertex: " << id << ", pagerank: " << kv.second << "\n"; + } + std::string res_string = output_stream.str(); + results::CollectiveResults results; + auto result = results.add_results(); + + result->mutable_record() + ->add_columns() + ->mutable_entry() + ->mutable_element() + ->mutable_object() + ->set_str(res_string); + + output.put_string_view(results.SerializeAsString()); + + txn.Commit(); + return true; +} + +AppWrapper PageRankFactory::CreateApp(const GraphDB& db) { + return AppWrapper(new PageRank(), NULL); +} +} // namespace gs diff --git a/flex/engines/graph_db/app/builtin/pagerank.h b/flex/engines/graph_db/app/builtin/pagerank.h new file mode 100644 index 000000000000..46d31bce78e6 --- /dev/null +++ b/flex/engines/graph_db/app/builtin/pagerank.h @@ -0,0 +1,52 @@ +/** Copyright 2020 Alibaba Group Holding Limited. + * + * Licensed 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. + */ + +#ifndef ENGINES_GRAPH_DB_APP_BUILDIN_PAGERANK_H_ +#define ENGINES_GRAPH_DB_APP_BUILDIN_PAGERANK_H_ +#include "flex/engines/graph_db/database/graph_db_session.h" +#include "flex/engines/hqps_db/app/interactive_app_base.h" + +namespace gs { +// A simple app to count the number of vertices of a given label. +class PageRank : public CypherInternalPbWriteAppBase { + public: + PageRank() + : damping_factor_(0.85), + max_iterations_(100), + epsilon_(1e-6), + vertex_label_id_(0), + edge_label_id_(0) {} + bool DoQuery(GraphDBSession& sess, Decoder& input, Encoder& output) override; + + private: + double damping_factor_; + int max_iterations_; + double epsilon_; + + label_t vertex_label_id_; + label_t edge_label_id_; +}; + +class PageRankFactory : public AppFactoryBase { + public: + PageRankFactory() = default; + ~PageRankFactory() = default; + + AppWrapper CreateApp(const GraphDB& db) override; +}; + +} // namespace gs + +#endif // ENGINES_GRAPH_DB_APP_BUILDIN_PAGERANK_H_ \ No newline at end of file diff --git a/flex/engines/graph_db/database/graph_db.cc b/flex/engines/graph_db/database/graph_db.cc index 0aa50c6b0624..286674abba2a 100644 --- a/flex/engines/graph_db/database/graph_db.cc +++ b/flex/engines/graph_db/database/graph_db.cc @@ -16,6 +16,9 @@ #include "flex/engines/graph_db/database/graph_db.h" #include "flex/engines/graph_db/app/adhoc_app.h" #include "flex/engines/graph_db/app/builtin/count_vertices.h" +#include "flex/engines/graph_db/app/builtin/pagerank.h" +#include "flex/engines/graph_db/app/builtin/k_degree_neighbors.h" +#include "flex/engines/graph_db/app/builtin/TVSP.h" #include "flex/engines/graph_db/app/hqps_app.h" #include "flex/engines/graph_db/app/server_app.h" #include "flex/engines/graph_db/database/graph_db_session.h" @@ -408,6 +411,13 @@ void GraphDB::initApps( app_factories_[0] = std::make_shared(); app_factories_[Schema::BUILTIN_COUNT_VERTICES_PLUGIN_ID] = std::make_shared(); + app_factories_[Schema::BUILTIN_PAGERANK_PLUGIN_ID] = + std::make_shared(); + app_factories_[Schema::BUILTIN_K_DEGREE_NEIGHBORS_PLUGIN_ID] = + std::make_shared(); + app_factories_[Schema::BUILTIN_TVSP_PLUGIN_ID] = + std::make_shared(); + app_factories_[Schema::HQPS_ADHOC_READ_PLUGIN_ID] = std::make_shared(); app_factories_[Schema::HQPS_ADHOC_WRITE_PLUGIN_ID] = diff --git a/flex/storages/metadata/graph_meta_store.cc b/flex/storages/metadata/graph_meta_store.cc index 8a9041c272b2..ef7eff176fb3 100644 --- a/flex/storages/metadata/graph_meta_store.cc +++ b/flex/storages/metadata/graph_meta_store.cc @@ -56,6 +56,8 @@ const std::vector& get_builtin_plugin_metas() { static std::vector builtin_plugins; static bool initialized = false; if (!initialized) { + + // count_vertices PluginMeta count_vertices; count_vertices.id = "count_vertices"; count_vertices.name = "count_vertices"; @@ -69,6 +71,64 @@ const std::vector& get_builtin_plugin_metas() { count_vertices.returns.push_back({"count", PropertyType::kInt32}); initialized = true; builtin_plugins.push_back(count_vertices); + + // pagerank + PluginMeta pagerank; + pagerank.id = "pagerank"; + pagerank.name = "pagerank"; + pagerank.description = "A builtin plugin to calculate pagerank"; + pagerank.enable = true; + pagerank.runnable = true; + pagerank.type = "cypher"; + pagerank.creation_time = GetCurrentTimeStamp(); + pagerank.update_time = GetCurrentTimeStamp(); + pagerank.params.push_back({"vertex_label", PropertyType::kString}); + pagerank.params.push_back({"edge_label", PropertyType::kString}); + pagerank.params.push_back({"damping_factor_", PropertyType::kDouble}); + pagerank.params.push_back({"max_iterations_", PropertyType::kInt32}); + pagerank.params.push_back({"epsilon_", PropertyType::kDouble}); + pagerank.returns.push_back({"pagerank", PropertyType::kString}); + initialized = true; + builtin_plugins.push_back(pagerank); + + // k_neighbors + PluginMeta k_neighbors; + k_neighbors.id = "k_neighbors"; + k_neighbors.name = "k_neighbors"; + k_neighbors.description = "A builtin plugin to calculate k_neighbors"; + k_neighbors.enable = true; + k_neighbors.runnable = true; + k_neighbors.type = "cypher"; + k_neighbors.creation_time = GetCurrentTimeStamp(); + k_neighbors.update_time = GetCurrentTimeStamp(); + k_neighbors.params.push_back({"vid", PropertyType::kInt32}); + k_neighbors.params.push_back({"label_name", PropertyType::kString}); + k_neighbors.params.push_back({"k", PropertyType::kInt32}); + k_neighbors.returns.push_back({"k_neighbors", PropertyType::kString}); + initialized = true; + builtin_plugins.push_back(k_neighbors); + + // TVSP + PluginMeta TVSP; + TVSP.id = "TVSP"; + TVSP.name = "TVSP"; + TVSP.description = "A builtin plugin to calculate TVSP"; + TVSP.enable = true; + TVSP.runnable = true; + TVSP.type = "cypher"; + TVSP.creation_time = GetCurrentTimeStamp(); + TVSP.update_time = GetCurrentTimeStamp(); + TVSP.params.push_back({"label_name1", PropertyType::kString}); + TVSP.params.push_back({"vid1", PropertyType::kInt32}); + TVSP.params.push_back({"label_name2", PropertyType::kString}); + TVSP.params.push_back({"vid2", PropertyType::kInt32}); + TVSP.params.push_back({"label_name3", PropertyType::kString}); + TVSP.params.push_back({"vid3", PropertyType::kInt32}); + TVSP.returns.push_back({"TVSP", PropertyType::kString}); + initialized = true; + builtin_plugins.push_back(TVSP); + + initialized = true; } return builtin_plugins; } From a8ce71a85a2c17c3dfffba48a9280629ec5cfbd6 Mon Sep 17 00:00:00 2001 From: shizhichao Date: Thu, 26 Sep 2024 11:47:44 +0800 Subject: [PATCH 2/6] add three builtin add --- .../graph_db/app/builtin/k_hop_neighbors.cc | 121 +++++++++ .../graph_db/app/builtin/k_hop_neighbors.h | 38 +++ flex/engines/graph_db/app/builtin/pagerank.cc | 147 +++++------ flex/engines/graph_db/app/builtin/pagerank.h | 11 +- .../app/builtin/shortest_path_among_three.cc | 231 ++++++++++++++++++ .../app/builtin/shortest_path_among_three.h | 44 ++++ flex/engines/graph_db/database/graph_db.cc | 6 +- flex/storages/metadata/graph_meta_store.cc | 47 ++-- flex/storages/rt_mutable_graph/schema.h | 19 +- 9 files changed, 559 insertions(+), 105 deletions(-) create mode 100644 flex/engines/graph_db/app/builtin/k_hop_neighbors.cc create mode 100644 flex/engines/graph_db/app/builtin/k_hop_neighbors.h create mode 100644 flex/engines/graph_db/app/builtin/shortest_path_among_three.cc create mode 100644 flex/engines/graph_db/app/builtin/shortest_path_among_three.h diff --git a/flex/engines/graph_db/app/builtin/k_hop_neighbors.cc b/flex/engines/graph_db/app/builtin/k_hop_neighbors.cc new file mode 100644 index 000000000000..7a5053ea2774 --- /dev/null +++ b/flex/engines/graph_db/app/builtin/k_hop_neighbors.cc @@ -0,0 +1,121 @@ +/** Copyright 2020 Alibaba Group Holding Limited. + * + * Licensed 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. + */ +#include "flex/engines/graph_db/app/builtin/k_hop_neighbors.h" + +namespace gs { + +bool KNeighbors::DoQuery(GraphDBSession& sess, Decoder& input, + Encoder& output) { + auto txn = sess.GetReadTransaction(); + Schema schema_ = txn.schema(); + if (input.empty()) { + return false; + } + int64_t vertex_id_ = input.get_long(); + std::string label_name{input.get_string()}; + int k = input.get_int(); + + if (k <= 0) { + output.put_string_view("k must be greater than 0."); + return false; + } + if (!schema_.has_vertex_label(label_name)) { + output.put_string_view("The requested label doesn't exits."); + return false; // The requested label doesn't exits. + } + label_t vertex_label_ = schema_.get_vertex_label_id(label_name); + + std::unordered_set k_neighbors; + + int vertex_size_ = (int) schema_.vertex_label_num(); + int edge_size_ = (int) schema_.edge_label_num(); + + std::vector nei_index_; + std::vector nei_label_; + std::vector next_nei_indexs_; + std::vector next_nei_label_; + + nei_label_.push_back(vertex_label_); + vid_t vertex_index{}; + if (!txn.GetVertexIndex(vertex_label_, (int64_t) vertex_id_, vertex_index)) { + output.put_string_view("get index fail."); + return false; + } + nei_index_.push_back(vertex_index); + // get k hop neighbors + while (!nei_index_.empty() && k > 0) { + for (long unsigned int i = 0; i < nei_index_.size(); i++) { + for (int j = 0; j < vertex_size_; j++) { + for (int k = 0; k < edge_size_; k++) { + if (schema_.has_edge_label(label_t(nei_label_[i]), label_t(j), + label_t(k))) { + auto outedges = txn.GetOutEdgeIterator( + nei_label_[i], nei_index_[i], j, + k); // 1.self_label 2.self_index 3.edge_label 4.nei_label + while (outedges.IsValid()) { + auto neighbor = outedges.GetNeighbor(); + int64_t vid = txn.GetVertexId(j, neighbor).AsInt64(); + if (k_neighbors.find(vid) == k_neighbors.end()) { + next_nei_label_.push_back(j); + next_nei_indexs_.push_back(neighbor); + k_neighbors.insert(vid); + } + outedges.Next(); + } + } + if (schema_.has_edge_label(label_t(j), label_t(nei_label_[i]), + label_t(k))) { + auto inedges = txn.GetInEdgeIterator( + nei_label_[i], nei_index_[i], j, + k); // 1.self_label 2.self_index 3.edge_label 4.nei_label + while (inedges.IsValid()) { + auto neighbor = inedges.GetNeighbor(); + int64_t vid = txn.GetVertexId(j, neighbor).AsInt64(); + if (k_neighbors.find(vid) == k_neighbors.end()) { + next_nei_label_.push_back(j); + next_nei_indexs_.push_back(neighbor); + k_neighbors.insert(vid); + } + inedges.Next(); + } + } + } + } + } + nei_index_ = next_nei_indexs_; + nei_label_ = next_nei_label_; + next_nei_label_.clear(); + next_nei_indexs_.clear(); + k--; + } + results::CollectiveResults results; + for (auto vid : k_neighbors) { + auto result = results.add_results(); + result->mutable_record() + ->add_columns() + ->mutable_entry() + ->mutable_element() + ->mutable_object() + ->set_i64(vid); + } + output.put_string_view(results.SerializeAsString()); + txn.Commit(); + return true; +} + +AppWrapper KNeighborsFactory::CreateApp(const GraphDB& db) { + return AppWrapper(new KNeighbors(), NULL); +} +} // namespace gs diff --git a/flex/engines/graph_db/app/builtin/k_hop_neighbors.h b/flex/engines/graph_db/app/builtin/k_hop_neighbors.h new file mode 100644 index 000000000000..81d58dc264ae --- /dev/null +++ b/flex/engines/graph_db/app/builtin/k_hop_neighbors.h @@ -0,0 +1,38 @@ +/** Copyright 2020 Alibaba Group Holding Limited. + * + * Licensed 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. + */ + +#ifndef ENGINES_GRAPH_DB_APP_BUILDIN_K_HOP_NEIGHBORS_ +#define ENGINES_GRAPH_DB_APP_BUILDIN_K_HOP_NEIGHBORS_ +#include "flex/engines/graph_db/database/graph_db_session.h" +#include "flex/engines/hqps_db/app/interactive_app_base.h" + +namespace gs { +class KNeighbors : public CypherInternalPbWriteAppBase { + public: + KNeighbors() {} + bool DoQuery(GraphDBSession& sess, Decoder& input, Encoder& output) override; +}; + +class KNeighborsFactory : public AppFactoryBase { + public: + KNeighborsFactory() = default; + ~KNeighborsFactory() = default; + + AppWrapper CreateApp(const GraphDB& db) override; +}; + +} // namespace gs + +#endif // ENGINES_GRAPH_DB_APP_BUILDIN_K_HOP_NEIGHBORS_ \ No newline at end of file diff --git a/flex/engines/graph_db/app/builtin/pagerank.cc b/flex/engines/graph_db/app/builtin/pagerank.cc index d32e6cdbff9a..42555551c4a8 100644 --- a/flex/engines/graph_db/app/builtin/pagerank.cc +++ b/flex/engines/graph_db/app/builtin/pagerank.cc @@ -16,113 +16,122 @@ namespace gs { - -bool PageRank::DoQuery(GraphDBSession& sess, Decoder& input, - Encoder& output) { - // First get the read transaction. +bool PageRank::DoQuery(GraphDBSession& sess, Decoder& input, Encoder& output) { auto txn = sess.GetReadTransaction(); - // We expect one param of type string from decoder. if (input.empty()) { + output.put_string_view( + "Arguments required(vertex_label, edge_label, damping_factor_, max_iterations_, epsilon_)\n \ + for example:(\"person\", \"knows\", 0.85, 100, 0.000001)"); return false; } + std::string vertex_label{input.get_string()}; std::string edge_label{input.get_string()}; - if(!input.empty()) { - damping_factor_ = input.get_double(); - max_iterations_ = input.get_int(); - epsilon_ = input.get_double(); + damping_factor_ = input.get_double(); + max_iterations_ = input.get_int(); + epsilon_ = input.get_double(); + + if (!sess.schema().has_vertex_label(vertex_label)) { + output.put_string_view("The requested vertex label doesn't exits."); + return false; + } + if (!sess.schema().has_edge_label(vertex_label, vertex_label, edge_label)) { + output.put_string_view("The requested edge label doesn't exits."); + return false; + } + if (damping_factor_ < 0 || damping_factor_ >= 1) { + output.put_string_view( + "The value of the damping_factor_ is between 0 and 1."); + return false; + } + if (max_iterations_ <= 0) { + output.put_string_view("max_iterations_ must be greater than 0."); + return false; + } + if (epsilon_ < 0 || epsilon_ >= 1) { + output.put_string_view("The value of the epsilon_ is between 0 and 1."); + return false; } vertex_label_id_ = sess.schema().get_vertex_label_id(vertex_label); edge_label_id_ = sess.schema().get_edge_label_id(edge_label); - // 统计顶点数量 auto num_vertices = txn.GetVertexNum(vertex_label_id_); - // 初始化每个顶点的PageRank值为 1.0 / num_vertices std::unordered_map pagerank; std::unordered_map new_pagerank; auto vertex_iter = txn.GetVertexIterator(vertex_label_id_); while (vertex_iter.IsValid()) { - vid_t vid = vertex_iter.GetIndex(); - pagerank[vid] = 1.0 / num_vertices; - new_pagerank[vid] = 0.0; - vertex_iter.Next(); + vid_t vid = vertex_iter.GetIndex(); + pagerank[vid] = 1.0 / num_vertices; + new_pagerank[vid] = 0.0; + vertex_iter.Next(); } - // 获取点的出度 std::unordered_map outdegree; - // 开始迭代计算PageRank值 for (int iter = 0; iter < max_iterations_; ++iter) { - // 初始化新的PageRank值 - for (auto& kv : new_pagerank) { - kv.second = 0.0; - } + for (auto& kv : new_pagerank) { + kv.second = 0.0; + } - // 遍历所有顶点 - auto vertex_iter = txn.GetVertexIterator(vertex_label_id_); - while (vertex_iter.IsValid()) { + auto vertex_iter = txn.GetVertexIterator(vertex_label_id_); + while (vertex_iter.IsValid()) { vid_t v = vertex_iter.GetIndex(); - - // 遍历所有出边并累加其PageRank贡献值 + double sum = 0.0; - auto edges = txn.GetInEdgeIterator(vertex_label_id_, v, vertex_label_id_, edge_label_id_); - while(edges.IsValid()){ - auto neighbor = edges.GetNeighbor(); - if(outdegree[neighbor] == 0){ - auto out_edges = txn.GetOutEdgeIterator(vertex_label_id_, neighbor, vertex_label_id_, edge_label_id_); - while(out_edges.IsValid()){ - outdegree[neighbor]++; - out_edges.Next(); - } + auto edges = txn.GetInEdgeIterator(vertex_label_id_, v, vertex_label_id_, + edge_label_id_); + while (edges.IsValid()) { + auto neighbor = edges.GetNeighbor(); + if (outdegree[neighbor] == 0) { + auto out_edges = txn.GetOutEdgeIterator( + vertex_label_id_, neighbor, vertex_label_id_, edge_label_id_); + while (out_edges.IsValid()) { + outdegree[neighbor]++; + out_edges.Next(); } - sum += pagerank[neighbor] / outdegree[neighbor]; - edges.Next(); + } + sum += pagerank[neighbor] / outdegree[neighbor]; + edges.Next(); } - // 计算新的PageRank值 - new_pagerank[v] = damping_factor_ * sum + (1.0 - damping_factor_) / num_vertices; + new_pagerank[v] = + damping_factor_ * sum + (1.0 - damping_factor_) / num_vertices; vertex_iter.Next(); - } + } - // 检查收敛 - double diff = 0.0; - for (const auto& kv : pagerank) { - diff += std::abs(new_pagerank[kv.first] - kv.second); - } + double diff = 0.0; + for (const auto& kv : pagerank) { + diff += std::abs(new_pagerank[kv.first] - kv.second); + } - // 如果收敛,则停止迭代 - if (diff < epsilon_) { - break; - } + if (diff < epsilon_) { + break; + } - // 交换pagerank与new_pagerank的内容 - std::swap(pagerank, new_pagerank); + std::swap(pagerank, new_pagerank); } - std::ostringstream output_stream; - for(auto kv : pagerank) { - auto id =txn.GetVertexId(vertex_label_id_, kv.first).AsInt64(); - // output.put_int(static_cast(id)); - // output.put_double(kv.second); - output_stream << "vertex: " << id << ", pagerank: " << kv.second << "\n"; - } - std::string res_string = output_stream.str(); results::CollectiveResults results; - auto result = results.add_results(); - - result->mutable_record() - ->add_columns() - ->mutable_entry() - ->mutable_element() - ->mutable_object() - ->set_str(res_string); - - output.put_string_view(results.SerializeAsString()); + + for (auto kv : pagerank) { + auto id = txn.GetVertexId(vertex_label_id_, kv.first).to_string(); + std::string res_string = + "vertex: " + id + ", pagerank: " + std::to_string(kv.second); + results.add_results() + ->mutable_record() + ->add_columns() + ->mutable_entry() + ->mutable_element() + ->mutable_object() + ->set_str(res_string); + } + + output.put_string_view(results.SerializeAsString()); txn.Commit(); return true; diff --git a/flex/engines/graph_db/app/builtin/pagerank.h b/flex/engines/graph_db/app/builtin/pagerank.h index 46d31bce78e6..abc6afc471db 100644 --- a/flex/engines/graph_db/app/builtin/pagerank.h +++ b/flex/engines/graph_db/app/builtin/pagerank.h @@ -19,13 +19,12 @@ #include "flex/engines/hqps_db/app/interactive_app_base.h" namespace gs { -// A simple app to count the number of vertices of a given label. class PageRank : public CypherInternalPbWriteAppBase { public: - PageRank() - : damping_factor_(0.85), - max_iterations_(100), - epsilon_(1e-6), + PageRank() + : damping_factor_(0.85), + max_iterations_(100), + epsilon_(1e-6), vertex_label_id_(0), edge_label_id_(0) {} bool DoQuery(GraphDBSession& sess, Decoder& input, Encoder& output) override; @@ -49,4 +48,4 @@ class PageRankFactory : public AppFactoryBase { } // namespace gs -#endif // ENGINES_GRAPH_DB_APP_BUILDIN_PAGERANK_H_ \ No newline at end of file +#endif \ No newline at end of file diff --git a/flex/engines/graph_db/app/builtin/shortest_path_among_three.cc b/flex/engines/graph_db/app/builtin/shortest_path_among_three.cc new file mode 100644 index 000000000000..a18fe8926d96 --- /dev/null +++ b/flex/engines/graph_db/app/builtin/shortest_path_among_three.cc @@ -0,0 +1,231 @@ +/** Copyright 2020 Alibaba Group Holding Limited. + * + * Licensed 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. + */ +#include "flex/engines/graph_db/app/builtin/shortest_path_among_three.h" + +namespace gs { + +bool ShortestPathAmongThree::DoQuery(GraphDBSession& sess, Decoder& input, + Encoder& output) { + ReadTransaction txn = sess.GetReadTransaction(); + if (input.empty()) { + return false; + } + Schema schema_ = txn.schema(); + std::string label_name1{input.get_string()}; + int64_t vid1 = input.get_long(); + std::string label_name2{input.get_string()}; + int64_t vid2 = input.get_long(); + std::string label_name3{input.get_string()}; + int64_t vid3 = input.get_long(); + + if (!schema_.has_vertex_label(label_name1) || + !schema_.has_vertex_label(label_name2) || + !schema_.has_vertex_label(label_name3)) { + output.put_string_view("The requested label doesn't exits."); + return false; + } + label_t label_v1 = schema_.get_vertex_label_id(label_name1); + label_t label_v2 = schema_.get_vertex_label_id(label_name2); + label_t label_v3 = schema_.get_vertex_label_id(label_name3); + vid_t index_v1{}; + vid_t index_v2{}; + vid_t index_v3{}; + if (!txn.GetVertexIndex(label_v1, (int64_t) vid1, index_v1) || + !txn.GetVertexIndex(label_v2, (int64_t) vid2, index_v2) || + !txn.GetVertexIndex(label_v3, (int64_t) vid3, index_v3)) { + output.put_string_view("get index fail."); + return false; + } + + std::vector v1v2result_; + std::vector v2v3result_; + std::vector v1v3result_; + + bool find_flag = true; + if (!ShortestPath(txn, label_v1, index_v1, label_v2, index_v2, v1v2result_)) { + find_flag = false; + } + if (find_flag && + !ShortestPath(txn, label_v2, index_v2, label_v3, index_v3, v2v3result_)) { + find_flag = false; + } + if (find_flag && + !ShortestPath(txn, label_v1, index_v1, label_v3, index_v3, v1v3result_)) { + find_flag = false; + } + std::string result_path = ""; + if (find_flag) { + // connect two shortest paths + std::vector TSP = + ConnectPath(v1v2result_, v2v3result_, v1v3result_); + for (auto it = TSP.begin(); it != TSP.end(); ++it) { + if (std::next(it) != TSP.end()) { + result_path += std::to_string(*it) + "--"; + } else { + result_path += std::to_string(*it); + } + } + } else { + result_path = "no path find!"; + } + + // create result string + results::CollectiveResults results; + auto result = results.add_results(); + result->mutable_record() + ->add_columns() + ->mutable_entry() + ->mutable_element() + ->mutable_object() + ->set_str(result_path); + + output.put_string_view(results.SerializeAsString()); + txn.Commit(); + return true; +} + +bool ShortestPathAmongThree::ShortestPath(const gs::ReadTransaction& txn, + label_t v1_l, vid_t v1_index, + label_t v2_l, vid_t v2_index, + std::vector& result_) { + Schema schema_ = txn.schema(); + int vertex_size_ = (int) schema_.vertex_label_num(); + int edge_size_ = (int) schema_.edge_label_num(); + + std::unordered_map parent; + std::vector nei_label_; + std::vector nei_index_; + int64_t v1_id = txn.GetVertexId(v1_l, v1_index).AsInt64(); + int64_t v2_id = txn.GetVertexId(v2_l, v2_index).AsInt64(); + + parent[v1_id] = -1; + nei_label_.push_back(v1_l); + nei_index_.push_back(v1_index); + std::unordered_set visit; + visit.insert(v1_id); + + std::vector next_nei_labels_; + std::vector next_nei_indexs_; + bool find = false; + while (!nei_label_.empty() && !find) { + for (long unsigned int i = 0; i < nei_index_.size(); i++) { + for (int j = 0; j < vertex_size_; j++) { + for (int k = 0; k < edge_size_; k++) { + if (schema_.has_edge_label(label_t(nei_label_[i]), label_t(j), + label_t(k))) { + auto outedges = txn.GetOutEdgeIterator( + nei_label_[i], nei_index_[i], j, + k); // 1.self_label 2.self_index 3.edge_label 4.nei_label + while (outedges.IsValid()) { + auto neighbor = outedges.GetNeighbor(); + int64_t v_id = txn.GetVertexId(j, neighbor).AsInt64(); + if (visit.find(v_id) == visit.end()) { + next_nei_labels_.push_back(j); + next_nei_indexs_.push_back(neighbor); + visit.insert(v_id); + parent[v_id] = + txn.GetVertexId(nei_label_[i], nei_index_[i]).AsInt64(); + if (v_id == v2_id) { + find = true; + break; + } + } + outedges.Next(); + } + } + if (schema_.has_edge_label(label_t(j), label_t(nei_label_[i]), + label_t(k))) { + auto inedges = txn.GetInEdgeIterator( + nei_label_[i], nei_index_[i], j, + k); // 1.self_label 2.self_index 3.edge_label 4.nei_label + while (inedges.IsValid()) { + auto neighbor = inedges.GetNeighbor(); + int64_t v_id = txn.GetVertexId(j, neighbor).AsInt64(); + if (visit.find(v_id) == visit.end()) { + next_nei_labels_.push_back(j); + next_nei_indexs_.push_back(neighbor); + visit.insert(v_id); + parent[v_id] = + txn.GetVertexId(nei_label_[i], nei_index_[i]).AsInt64(); + if (v_id == v2_id) { + find = true; + break; + } + } + inedges.Next(); + } + } + } + if (find) + break; + } + if (find) + break; + } + if (find) + break; + nei_label_ = next_nei_labels_; + nei_index_ = next_nei_indexs_; + next_nei_labels_.clear(); + next_nei_indexs_.clear(); + } + if (find) { + int64_t v = v2_id; + while (v != -1) { + result_.push_back(v); + v = parent[v]; + } + std::reverse(result_.begin(), result_.end()); + return true; + } else { + return false; + } +} + +std::vector ShortestPathAmongThree::ConnectPath( + std::vector& path1, std::vector& path2, + std::vector& path3) { + std::vector TSP; + int v1v2size = (int) path1.size(); + int v2v3size = (int) path2.size(); + int v1v3size = (int) path3.size(); + if (v1v2size <= v2v3size && v1v3size <= v2v3size) { + for (int i = v1v2size - 1; i >= 0; i--) { + TSP.push_back(path1[i]); + } + for (int i = 1; i < v1v3size; i++) { + TSP.push_back(path3[i]); + } + } else if (v1v2size <= v1v3size && v2v3size <= v1v3size) { + for (int i = 0; i < v1v2size; i++) { + TSP.push_back(path1[i]); + } + for (int i = 1; i < v2v3size; i++) { + TSP.push_back(path2[i]); + } + } else if (v2v3size <= v1v2size && v1v3size <= v1v2size) { + for (int i = 0; i < v2v3size; i++) { + TSP.push_back(path2[i]); + } + for (int i = v1v3size - 2; i >= 0; i--) { + TSP.push_back(path3[i]); + } + } + return TSP; +} +AppWrapper ShortestPathAmongThreeFactory::CreateApp(const GraphDB& db) { + return AppWrapper(new ShortestPathAmongThree(), NULL); +} +} // namespace gs diff --git a/flex/engines/graph_db/app/builtin/shortest_path_among_three.h b/flex/engines/graph_db/app/builtin/shortest_path_among_three.h new file mode 100644 index 000000000000..da999af4c496 --- /dev/null +++ b/flex/engines/graph_db/app/builtin/shortest_path_among_three.h @@ -0,0 +1,44 @@ +/** Copyright 2020 Alibaba Group Holding Limited. + * + * Licensed 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. + */ + +#ifndef ENGINES_GRAPH_DB_APP_BUILDIN_SHORTEST_PATH_AMONG_THREE_H_ +#define ENGINES_GRAPH_DB_APP_BUILDIN_SHORTEST_PATH_AMONG_THREE_H_ +#include "flex/engines/graph_db/database/graph_db_session.h" +#include "flex/engines/hqps_db/app/interactive_app_base.h" + +namespace gs { +class ShortestPathAmongThree : public CypherInternalPbWriteAppBase { + public: + ShortestPathAmongThree() {} + bool DoQuery(GraphDBSession& sess, Decoder& input, Encoder& output) override; + bool ShortestPath(const gs::ReadTransaction& txn, label_t v1_l, + vid_t v1_index, label_t v2_l, vid_t v2_index, + std::vector& result_); + std::vector ConnectPath(std::vector& path1, + std::vector& path2, + std::vector& path3); +}; + +class ShortestPathAmongThreeFactory : public AppFactoryBase { + public: + ShortestPathAmongThreeFactory() = default; + ~ShortestPathAmongThreeFactory() = default; + + AppWrapper CreateApp(const GraphDB& db) override; +}; + +} // namespace gs + +#endif \ No newline at end of file diff --git a/flex/engines/graph_db/database/graph_db.cc b/flex/engines/graph_db/database/graph_db.cc index 286674abba2a..2f3ad08306c8 100644 --- a/flex/engines/graph_db/database/graph_db.cc +++ b/flex/engines/graph_db/database/graph_db.cc @@ -16,9 +16,9 @@ #include "flex/engines/graph_db/database/graph_db.h" #include "flex/engines/graph_db/app/adhoc_app.h" #include "flex/engines/graph_db/app/builtin/count_vertices.h" +#include "flex/engines/graph_db/app/builtin/k_hop_neighbors.h" #include "flex/engines/graph_db/app/builtin/pagerank.h" -#include "flex/engines/graph_db/app/builtin/k_degree_neighbors.h" -#include "flex/engines/graph_db/app/builtin/TVSP.h" +#include "flex/engines/graph_db/app/builtin/shortest_path_among_three.h" #include "flex/engines/graph_db/app/hqps_app.h" #include "flex/engines/graph_db/app/server_app.h" #include "flex/engines/graph_db/database/graph_db_session.h" @@ -416,7 +416,7 @@ void GraphDB::initApps( app_factories_[Schema::BUILTIN_K_DEGREE_NEIGHBORS_PLUGIN_ID] = std::make_shared(); app_factories_[Schema::BUILTIN_TVSP_PLUGIN_ID] = - std::make_shared(); + std::make_shared(); app_factories_[Schema::HQPS_ADHOC_READ_PLUGIN_ID] = std::make_shared(); diff --git a/flex/storages/metadata/graph_meta_store.cc b/flex/storages/metadata/graph_meta_store.cc index ef7eff176fb3..286762d22b9a 100644 --- a/flex/storages/metadata/graph_meta_store.cc +++ b/flex/storages/metadata/graph_meta_store.cc @@ -56,7 +56,6 @@ const std::vector& get_builtin_plugin_metas() { static std::vector builtin_plugins; static bool initialized = false; if (!initialized) { - // count_vertices PluginMeta count_vertices; count_vertices.id = "count_vertices"; @@ -69,7 +68,6 @@ const std::vector& get_builtin_plugin_metas() { count_vertices.update_time = GetCurrentTimeStamp(); count_vertices.params.push_back({"labelName", PropertyType::kString}); count_vertices.returns.push_back({"count", PropertyType::kInt32}); - initialized = true; builtin_plugins.push_back(count_vertices); // pagerank @@ -88,7 +86,6 @@ const std::vector& get_builtin_plugin_metas() { pagerank.params.push_back({"max_iterations_", PropertyType::kInt32}); pagerank.params.push_back({"epsilon_", PropertyType::kDouble}); pagerank.returns.push_back({"pagerank", PropertyType::kString}); - initialized = true; builtin_plugins.push_back(pagerank); // k_neighbors @@ -101,32 +98,36 @@ const std::vector& get_builtin_plugin_metas() { k_neighbors.type = "cypher"; k_neighbors.creation_time = GetCurrentTimeStamp(); k_neighbors.update_time = GetCurrentTimeStamp(); - k_neighbors.params.push_back({"vid", PropertyType::kInt32}); + k_neighbors.params.push_back({"vid", PropertyType::kInt64}); k_neighbors.params.push_back({"label_name", PropertyType::kString}); k_neighbors.params.push_back({"k", PropertyType::kInt32}); k_neighbors.returns.push_back({"k_neighbors", PropertyType::kString}); - initialized = true; builtin_plugins.push_back(k_neighbors); - // TVSP - PluginMeta TVSP; - TVSP.id = "TVSP"; - TVSP.name = "TVSP"; - TVSP.description = "A builtin plugin to calculate TVSP"; - TVSP.enable = true; - TVSP.runnable = true; - TVSP.type = "cypher"; - TVSP.creation_time = GetCurrentTimeStamp(); - TVSP.update_time = GetCurrentTimeStamp(); - TVSP.params.push_back({"label_name1", PropertyType::kString}); - TVSP.params.push_back({"vid1", PropertyType::kInt32}); - TVSP.params.push_back({"label_name2", PropertyType::kString}); - TVSP.params.push_back({"vid2", PropertyType::kInt32}); - TVSP.params.push_back({"label_name3", PropertyType::kString}); - TVSP.params.push_back({"vid3", PropertyType::kInt32}); - TVSP.returns.push_back({"TVSP", PropertyType::kString}); + // shortest_path_among_three + PluginMeta shortest_path_among_three; + shortest_path_among_three.id = "shortest_path_among_three"; + shortest_path_among_three.name = "shortest_path_among_three"; + shortest_path_among_three.description = + "A builtin plugin to calculate shortest_path_among_three"; + shortest_path_among_three.enable = true; + shortest_path_among_three.runnable = true; + shortest_path_among_three.type = "cypher"; + shortest_path_among_three.creation_time = GetCurrentTimeStamp(); + shortest_path_among_three.update_time = GetCurrentTimeStamp(); + shortest_path_among_three.params.push_back( + {"label_name1", PropertyType::kString}); + shortest_path_among_three.params.push_back({"vid1", PropertyType::kInt64}); + shortest_path_among_three.params.push_back( + {"label_name2", PropertyType::kString}); + shortest_path_among_three.params.push_back({"vid2", PropertyType::kInt64}); + shortest_path_among_three.params.push_back( + {"label_name3", PropertyType::kString}); + shortest_path_among_three.params.push_back({"vid3", PropertyType::kInt64}); + shortest_path_among_three.returns.push_back( + {"shortest_path_among_three", PropertyType::kString}); initialized = true; - builtin_plugins.push_back(TVSP); + builtin_plugins.push_back(shortest_path_among_three); initialized = true; } diff --git a/flex/storages/rt_mutable_graph/schema.h b/flex/storages/rt_mutable_graph/schema.h index 21ef5a68f62e..1f696aabd921 100644 --- a/flex/storages/rt_mutable_graph/schema.h +++ b/flex/storages/rt_mutable_graph/schema.h @@ -31,7 +31,7 @@ class Schema { // How many built-in plugins are there. // Currently only one builtin plugin, SERVER_APP is supported. static constexpr uint8_t RESERVED_PLUGIN_NUM = 1; - static constexpr uint8_t MAX_PLUGIN_ID = 251; + static constexpr uint8_t MAX_PLUGIN_ID = 248; static constexpr uint8_t ADHOC_READ_PLUGIN_ID = 253; static constexpr uint8_t HQPS_ADHOC_READ_PLUGIN_ID = 254; static constexpr uint8_t HQPS_ADHOC_WRITE_PLUGIN_ID = 255; @@ -44,14 +44,25 @@ class Schema { static constexpr const uint16_t STRING_DEFAULT_MAX_LENGTH = 256; // The builtin plugins are reserved for the system. - static constexpr uint8_t BUILTIN_PLUGIN_NUM = 1; + static constexpr uint8_t BUILTIN_PLUGIN_NUM = 4; + static constexpr uint8_t BUILTIN_COUNT_VERTICES_PLUGIN_ID = 252; static constexpr const char* BUILTIN_COUNT_VERTICES_PLUGIN_NAME = "count_vertices"; + static constexpr uint8_t BUILTIN_PAGERANK_PLUGIN_ID = 251; + static constexpr const char* BUILTIN_PAGERANK_PLUGIN_NAME = "pagerank"; + static constexpr uint8_t BUILTIN_K_DEGREE_NEIGHBORS_PLUGIN_ID = 250; + static constexpr const char* BUILTIN_K_DEGREE_NEIGHBORS_PLUGIN_NAME = + "k_neighbors"; + static constexpr uint8_t BUILTIN_TVSP_PLUGIN_ID = 249; + static constexpr const char* BUILTIN_TVSP_PLUGIN_NAME = + "shortest_path_among_three"; static constexpr const char* BUILTIN_PLUGIN_NAMES[BUILTIN_PLUGIN_NUM] = { - BUILTIN_COUNT_VERTICES_PLUGIN_NAME}; + BUILTIN_COUNT_VERTICES_PLUGIN_NAME, BUILTIN_PAGERANK_PLUGIN_NAME, + BUILTIN_K_DEGREE_NEIGHBORS_PLUGIN_NAME, BUILTIN_TVSP_PLUGIN_NAME}; static constexpr uint8_t BUILTIN_PLUGIN_IDS[BUILTIN_PLUGIN_NUM] = { - BUILTIN_COUNT_VERTICES_PLUGIN_ID}; + BUILTIN_COUNT_VERTICES_PLUGIN_ID, BUILTIN_PAGERANK_PLUGIN_ID, + BUILTIN_K_DEGREE_NEIGHBORS_PLUGIN_ID, BUILTIN_TVSP_PLUGIN_ID}; // An array containing all compatible versions of schema. static const std::vector COMPATIBLE_VERSIONS; From 597e9bd935c80551ef56b94b82350c483cd188f5 Mon Sep 17 00:00:00 2001 From: shizhichao Date: Thu, 26 Sep 2024 13:15:34 +0800 Subject: [PATCH 3/6] Remove deleted files --- flex/engines/graph_db/app/builtin/TVSP.cc | 228 ------------------ flex/engines/graph_db/app/builtin/TVSP.h | 50 ---- .../app/builtin/k_degree_neighbors.cc | 116 --------- .../graph_db/app/builtin/k_degree_neighbors.h | 43 ---- 4 files changed, 437 deletions(-) delete mode 100644 flex/engines/graph_db/app/builtin/TVSP.cc delete mode 100644 flex/engines/graph_db/app/builtin/TVSP.h delete mode 100644 flex/engines/graph_db/app/builtin/k_degree_neighbors.cc delete mode 100644 flex/engines/graph_db/app/builtin/k_degree_neighbors.h diff --git a/flex/engines/graph_db/app/builtin/TVSP.cc b/flex/engines/graph_db/app/builtin/TVSP.cc deleted file mode 100644 index 17efb1af639f..000000000000 --- a/flex/engines/graph_db/app/builtin/TVSP.cc +++ /dev/null @@ -1,228 +0,0 @@ -/** Copyright 2020 Alibaba Group Holding Limited. - * - * Licensed 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. - */ -#include "flex/engines/graph_db/app/builtin/TVSP.h" - -namespace gs { - -bool TVSP::DoQuery(GraphDBSession& sess, Decoder& input,Encoder& output) { - ReadTransaction txn = sess.GetReadTransaction(); - if (input.empty()) { - return false; - } - Schema schema_ = txn.schema(); - std::string label_name1{input.get_string()}; - vid_t vid1=input.get_int(); - std::string label_name2{input.get_string()}; - vid_t vid2=input.get_int(); - std::string label_name3{input.get_string()}; - vid_t vid3=input.get_int(); - - if(!schema_.has_vertex_label(label_name1)||!schema_.has_vertex_label(label_name2) - ||!schema_.has_vertex_label(label_name3)){ - output.put_string_view("The requested label doesn't exits."); - return false; // The requested label doesn't exits. - } - label_t label_v1=schema_.get_vertex_label_id(label_name1); - label_t label_v2=schema_.get_vertex_label_id(label_name2); - label_t label_v3=schema_.get_vertex_label_id(label_name3); - vid_t index_v1{}; - vid_t index_v2{}; - vid_t index_v3{}; - if(!txn.GetVertexIndex(label_v1, (int64_t)vid1, index_v1)|| - !txn.GetVertexIndex(label_v2, (int64_t)vid2, index_v2)|| - !txn.GetVertexIndex(label_v3, (int64_t)vid3, index_v3)) - { - output.put_string_view("get index fail."); - return false; - } - - uint vertex_num = 0 ; - for(label_t i = 0 ; i v1v2result_; - std::vector v2v3result_; - std::vector v1v3result_; - - bool find_flag = true; - if(!ShortestPath(txn,label_v1,index_v1,label_v2,index_v2,v1v2result_,vertex_num)){ - find_flag=false; - } - if(find_flag&&!ShortestPath(txn,label_v2,index_v2,label_v3,index_v3,v2v3result_,vertex_num)){ - find_flag=false; - } - if(find_flag&&!ShortestPath(txn,label_v1,index_v1,label_v3,index_v3,v1v3result_,vertex_num)){ - find_flag=false; - } - std::string result_path = ""; - if(find_flag){ - //选择最短的两条路径进行连接 - std::vector TSP = ConnectPath(v1v2result_,v2v3result_,v1v3result_); - for(auto it = TSP.begin(); it != TSP.end(); ++it){ - if (std::next(it) != TSP.end()) { - result_path += std::to_string(*it)+"--"; // 如果当前元素不是最后一个,则添加空格 - } - else{ - result_path += std::to_string(*it); - } - } - } - else{ - result_path="no path find!"; - } - - // 向CollectiveResults中添加多个Results对象 - results::CollectiveResults results; - auto result = results.add_results(); - result->mutable_record() - ->add_columns() - ->mutable_entry() - ->mutable_element() - ->mutable_object() - ->set_str(result_path); - - output.put_string_view(results.SerializeAsString()); - txn.Commit(); - return true; -} - -bool TVSP::ShortestPath(const gs::ReadTransaction& txn, label_t v1_l,vid_t v1_index,label_t v2_l,vid_t v2_index,std::vector &result_, uint vertex_num){ - Schema schema_ = txn.schema(); - int vertex_size_ = (int)schema_.vertex_label_num(); - int edge_size_ = (int)schema_.edge_label_num(); - - std::vector visited(vertex_num+1, false); - std::unordered_map parent; - std::vector nei_label_; - std::vector nei_index_; - int64_t v1_id = txn.GetVertexId(v1_l, v1_index).AsInt64(); - int64_t v2_id = txn.GetVertexId(v2_l, v2_index).AsInt64(); - - // std::cout<<"v1: "< next_nei_labels_; - std::vector next_nei_indexs_; - bool find = false; - while(!nei_label_.empty()&&!find) { - for(long unsigned int i = 0 ; i< nei_index_.size();i++){ - for(int j = 0 ; j TVSP::ConnectPath(std::vector &path1,std::vector &path2, - std::vector &path3){ - std::vector TSP; - int v1v2size = (int)path1.size(); - int v2v3size = (int)path2.size(); - int v1v3size = (int)path3.size(); - if(v1v2size<=v2v3size&&v1v3size<=v2v3size){ - for(int i =v1v2size-1;i>=0;i--){ - TSP.push_back(path1[i]); - } - for(int i = 1;i=0;i--){ - TSP.push_back(path3[i]); - } - } - return TSP; -} -AppWrapper TVSPFactory::CreateApp(const GraphDB& db) { - return AppWrapper(new TVSP(), NULL); -} -} // namespace gs diff --git a/flex/engines/graph_db/app/builtin/TVSP.h b/flex/engines/graph_db/app/builtin/TVSP.h deleted file mode 100644 index 0c43c2c378d9..000000000000 --- a/flex/engines/graph_db/app/builtin/TVSP.h +++ /dev/null @@ -1,50 +0,0 @@ -/** Copyright 2020 Alibaba Group Holding Limited. - * - * Licensed 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. - */ - -#ifndef ENGINES_GRAPH_DB_APP_BUILDIN_TVSP_H_ -#define ENGINES_GRAPH_DB_APP_BUILDIN_TVSP_H_ -#include "flex/engines/graph_db/database/graph_db_session.h" -#include "flex/engines/hqps_db/app/interactive_app_base.h" - -namespace gs { -// A simple app to count the number of vertices of a given label. -class TVSP : public CypherInternalPbWriteAppBase { - private: -// std::string label_name1; -// int32_t vid1; -// std::string label_name2; -// int32_t vid2; -// std::string label_name3; -// int32_t vid3; - - public: - TVSP() {} - bool DoQuery(GraphDBSession& sess, Decoder& input, Encoder& output) override; - bool ShortestPath(const gs::ReadTransaction& txn, label_t v1_l,vid_t v1_index,label_t v2_l,vid_t v2_index,std::vector &result_, uint vertex_num); - std::vector ConnectPath(std::vector &path1,std::vector &path2,std::vector &path3); - -}; - -class TVSPFactory : public AppFactoryBase { - public: - TVSPFactory() = default; - ~TVSPFactory() = default; - - AppWrapper CreateApp(const GraphDB& db) override; -}; - -} // namespace gs - -#endif // ENGINES_GRAPH_DB_APP_BUILDIN_TVSP_H_ \ No newline at end of file diff --git a/flex/engines/graph_db/app/builtin/k_degree_neighbors.cc b/flex/engines/graph_db/app/builtin/k_degree_neighbors.cc deleted file mode 100644 index f5fa5deaeeb5..000000000000 --- a/flex/engines/graph_db/app/builtin/k_degree_neighbors.cc +++ /dev/null @@ -1,116 +0,0 @@ -/** Copyright 2020 Alibaba Group Holding Limited. - * - * Licensed 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. - */ -#include "flex/engines/graph_db/app/builtin/k_degree_neighbors.h" - -namespace gs { - -bool KNeighbors::DoQuery(GraphDBSession& sess, Decoder& input, - Encoder& output) { - // 创建一个CollectiveResults对象 - auto txn = sess.GetReadTransaction(); - Schema schema_ = txn.schema(); - if (input.empty()) { - return false; - } - this->vertex_id_=input.get_int(); - std::string label_name { input.get_string()}; - this->k=input.get_int(); - - if(k<=0) { - output.put_string_view("k must be greater than 0."); - return false; - } - if(!schema_.has_vertex_label(label_name)){ - output.put_string_view("The requested label doesn't exits."); - return false; // The requested label doesn't exits. - } - this->vertex_label_=schema_.get_vertex_label_id(label_name); - - - std::set k_neighbors; - - int vertex_size_ = (int)schema_.vertex_label_num(); - int edge_size_ = (int)schema_.edge_label_num(); - - std::vector nei_index_; - std::vector nei_label_; - std::vector next_nei_indexs_; - std::vector next_nei_label_; - - nei_label_.push_back(vertex_label_); - vid_t vertex_index{}; - if(!txn.GetVertexIndex(vertex_label_, (int64_t)vertex_id_, vertex_index)){ - output.put_string_view("get index fail."); - return false; - } - nei_index_.push_back(vertex_index); - //层次遍历得到k跳邻居 - while(!nei_index_.empty() && k > 0) { - for(long unsigned int i = 0 ; imutable_record() - ->add_columns() - ->mutable_entry() - ->mutable_element() - ->mutable_object() - ->set_str(res); - output.put_string_view(results.SerializeAsString()); - txn.Commit(); - return true; -} - -AppWrapper KNeighborsFactory::CreateApp(const GraphDB& db) { - return AppWrapper(new KNeighbors(), NULL); -} -} // namespace gs diff --git a/flex/engines/graph_db/app/builtin/k_degree_neighbors.h b/flex/engines/graph_db/app/builtin/k_degree_neighbors.h deleted file mode 100644 index 543c4212ddb8..000000000000 --- a/flex/engines/graph_db/app/builtin/k_degree_neighbors.h +++ /dev/null @@ -1,43 +0,0 @@ -/** Copyright 2020 Alibaba Group Holding Limited. - * - * Licensed 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. - */ - -#ifndef ENGINES_GRAPH_DB_APP_BUILDIN_K_DEGREE_NEI_ -#define ENGINES_GRAPH_DB_APP_BUILDIN_K_DEGREE_NEI_ -#include "flex/engines/graph_db/database/graph_db_session.h" -#include "flex/engines/hqps_db/app/interactive_app_base.h" - -namespace gs { -// A simple app to count the number of vertices of a given label. -class KNeighbors : public CypherInternalPbWriteAppBase { - private: - vid_t vertex_id_; - label_t vertex_label_; - int32_t k; - public: - KNeighbors() {} - bool DoQuery(GraphDBSession& sess, Decoder& input, Encoder& output) override; -}; - -class KNeighborsFactory : public AppFactoryBase { - public: - KNeighborsFactory() = default; - ~KNeighborsFactory() = default; - - AppWrapper CreateApp(const GraphDB& db) override; -}; - -} // namespace gs - -#endif // ENGINES_GRAPH_DB_APP_BUILDIN_COUNT_VERTICES_H_ \ No newline at end of file From 2dc4d50261ac0ff5f073d230b8843440dc1df88b Mon Sep 17 00:00:00 2001 From: shizhichao Date: Thu, 26 Sep 2024 15:32:42 +0800 Subject: [PATCH 4/6] add builtin app test --- .../sdk/python/gs_interactive/tests/test_robustness.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/flex/interactive/sdk/python/gs_interactive/tests/test_robustness.py b/flex/interactive/sdk/python/gs_interactive/tests/test_robustness.py index 093dc03b0aca..f662a4013b5c 100644 --- a/flex/interactive/sdk/python/gs_interactive/tests/test_robustness.py +++ b/flex/interactive/sdk/python/gs_interactive/tests/test_robustness.py @@ -135,4 +135,7 @@ def test_builtin_procedure(interactive_session,neo4j_session, create_modern_grap # Call the builtin procedure start_service_on_graph(interactive_session, create_modern_graph) call_procedure(neo4j_session, create_modern_graph, "count_vertices", '"person"') + call_procedure(neo4j_session, create_modern_graph, "pagerank", '"person"','"knows"','0.85','100','0000001') + call_procedure(neo4j_session, create_modern_graph, "k_neighbors",'1L','"person"','2') + call_procedure(neo4j_session, create_modern_graph, "shortest_path_among_three", '"person"','1L','"person"','2L','"person"','4L') From 42241b047e7f43455044d081ceaa3e54c6dabe30 Mon Sep 17 00:00:00 2001 From: shizhichao Date: Thu, 26 Sep 2024 17:12:44 +0800 Subject: [PATCH 5/6] add builtin app test --- .../sdk/python/gs_interactive/tests/conftest.py | 2 +- .../sdk/python/gs_interactive/tests/test_robustness.py | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/flex/interactive/sdk/python/gs_interactive/tests/conftest.py b/flex/interactive/sdk/python/gs_interactive/tests/conftest.py index b4402cbae0bd..c7019be340e5 100644 --- a/flex/interactive/sdk/python/gs_interactive/tests/conftest.py +++ b/flex/interactive/sdk/python/gs_interactive/tests/conftest.py @@ -396,7 +396,7 @@ def run_cypher_test_suite(neo4j_sess : Neo4jSession, graph_id: str, queries: lis submit_query_via_neo4j_endpoint(neo4j_sess, graph_id, query) def call_procedure(neo4j_sess : Neo4jSession, graph_id: str, proc_name: str, *args): - query = "CALL " + proc_name + "(" + ",".join(args) + ")" + query = "CALL " + proc_name + "(" + ",".join([str(item) for item in args]) + ")" result = neo4j_sess.run(query) for record in result: print(record) diff --git a/flex/interactive/sdk/python/gs_interactive/tests/test_robustness.py b/flex/interactive/sdk/python/gs_interactive/tests/test_robustness.py index f662a4013b5c..bf8b9c78c784 100644 --- a/flex/interactive/sdk/python/gs_interactive/tests/test_robustness.py +++ b/flex/interactive/sdk/python/gs_interactive/tests/test_robustness.py @@ -123,6 +123,7 @@ def test_procedure_creation(interactive_session, neo4j_session, create_modern_gr def test_builtin_procedure(interactive_session,neo4j_session, create_modern_graph): print("[Test builtin procedure]") + import_data_to_full_modern_graph(interactive_session, create_modern_graph) # Delete the builtin procedure should fail with pytest.raises(Exception): delete_procedure(interactive_session, create_modern_graph, "count_vertices") @@ -135,7 +136,7 @@ def test_builtin_procedure(interactive_session,neo4j_session, create_modern_grap # Call the builtin procedure start_service_on_graph(interactive_session, create_modern_graph) call_procedure(neo4j_session, create_modern_graph, "count_vertices", '"person"') - call_procedure(neo4j_session, create_modern_graph, "pagerank", '"person"','"knows"','0.85','100','0000001') - call_procedure(neo4j_session, create_modern_graph, "k_neighbors",'1L','"person"','2') - call_procedure(neo4j_session, create_modern_graph, "shortest_path_among_three", '"person"','1L','"person"','2L','"person"','4L') + call_procedure(neo4j_session, create_modern_graph, "pagerank", '"person"','"knows"',"0.85", "100", "0.000001") + call_procedure(neo4j_session, create_modern_graph, "k_neighbors", "1L",'"person"',"2") + call_procedure(neo4j_session, create_modern_graph, "shortest_path_among_three", '"person"', "1L", '"person"', "2L", '"person"',"4L") From c2a578be5bd52c69b651bf754828aa01681673e1 Mon Sep 17 00:00:00 2001 From: shizhichao Date: Fri, 27 Sep 2024 12:31:08 +0800 Subject: [PATCH 6/6] Modify k_neighbors return value --- flex/storages/metadata/graph_meta_store.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flex/storages/metadata/graph_meta_store.cc b/flex/storages/metadata/graph_meta_store.cc index 286762d22b9a..7d4a514eb9e3 100644 --- a/flex/storages/metadata/graph_meta_store.cc +++ b/flex/storages/metadata/graph_meta_store.cc @@ -101,7 +101,7 @@ const std::vector& get_builtin_plugin_metas() { k_neighbors.params.push_back({"vid", PropertyType::kInt64}); k_neighbors.params.push_back({"label_name", PropertyType::kString}); k_neighbors.params.push_back({"k", PropertyType::kInt32}); - k_neighbors.returns.push_back({"k_neighbors", PropertyType::kString}); + k_neighbors.returns.push_back({"k_neighbors", PropertyType::kInt64}); builtin_plugins.push_back(k_neighbors); // shortest_path_among_three