diff --git a/src/query/v2/requests.hpp b/src/query/v2/requests.hpp index da61339b3..8b6e523e7 100644 --- a/src/query/v2/requests.hpp +++ b/src/query/v2/requests.hpp @@ -26,6 +26,15 @@ namespace memgraph::msgs { +// TODO(gvolfing) introduce structure for property updates +// TODO(gvolfing) remove tuples from ExpandOne and add specific structs instead + +// TODO(gvolfing) discuss with kostas: +// - EdgeId +// - Everything about ExpandOne +// - Edge properties +// - Ctors + using coordinator::Hlc; using storage::v3::LabelId; @@ -41,6 +50,11 @@ using VertexId = std::pair<Label, PrimaryKey>; using Gid = size_t; using PropertyId = memgraph::storage::v3::PropertyId; +// struct PropertyUpdate{ +// PropertyId id; +// Value value; +// }; + struct EdgeType { uint64_t id; }; @@ -411,8 +425,13 @@ struct ExpandOneResultRow { // The drawback of this is currently the key of the map is always interpreted as a string in Value, not as an // integer, which should be in case of mapped properties. Vertex src_vertex; - std::optional<std::map<PropertyId, Value>> src_vertex_properties; + + // NOTE: If the desired edges are specified in the request, + // edges_with_specific_properties will have a value and it will + // return the properties as a vector of property values. The order + // of the values returned should be the same as the PropertyIds + // were defined in the request. std::optional<std::vector<std::tuple<VertexId, Gid, std::map<PropertyId, Value>>>> edges_with_all_properties; std::optional<std::vector<std::tuple<VertexId, Gid, std::vector<Value>>>> edges_with_specific_properties; }; diff --git a/src/storage/v3/shard_rsm.cpp b/src/storage/v3/shard_rsm.cpp index ca81df18d..13b800cab 100644 --- a/src/storage/v3/shard_rsm.cpp +++ b/src/storage/v3/shard_rsm.cpp @@ -113,17 +113,6 @@ std::vector<std::pair<memgraph::storage::v3::PropertyId, memgraph::storage::v3:: return ret; } -// std::vector<memgraph::storage::v3::PropertyValue> ConvertPropertyVector(const std::vector<Value> &&vec) { -// std::vector<memgraph::storage::v3::PropertyValue> ret; -// ret.reserve(vec.size()); - -// for (auto &elem : vec) { -// ret.push_back(ToPropertyValue((elem))); -// } - -// return ret; -// } - std::vector<memgraph::storage::v3::PropertyValue> ConvertPropertyVector(std::vector<Value> &&vec) { std::vector<memgraph::storage::v3::PropertyValue> ret; ret.reserve(vec.size()); @@ -712,7 +701,9 @@ msgs::ReadResponses ShardRsm::HandleRead(msgs::ExpandOneRequest &&req) { } /// Fill up connecting edges - std::vector<EdgeAccessor> edges; + std::vector<EdgeAccessor> in_edges; + std::vector<EdgeAccessor> out_edges; + switch (req.direction) { case msgs::EdgeDirection::OUT: { auto out_edges_result = v_acc->OutEdges(View::OLD); @@ -723,7 +714,7 @@ msgs::ReadResponses ShardRsm::HandleRead(msgs::ExpandOneRequest &&req) { action_successful = false; break; } - edges = out_edges_result.GetValue(); + out_edges = out_edges_result.GetValue(); break; } case msgs::EdgeDirection::IN: { @@ -735,12 +726,12 @@ msgs::ReadResponses ShardRsm::HandleRead(msgs::ExpandOneRequest &&req) { action_successful = false; break; } - edges = in_edges_result.GetValue(); + in_edges = in_edges_result.GetValue(); break; } case msgs::EdgeDirection::BOTH: { - std::vector<EdgeAccessor> in_edges; - std::vector<EdgeAccessor> out_edges; + // std::vector<EdgeAccessor> in_edges; + // std::vector<EdgeAccessor> out_edges; auto in_edges_result = v_acc->InEdges(View::OLD); if (in_edges_result.HasError()) { @@ -761,10 +752,6 @@ msgs::ReadResponses ShardRsm::HandleRead(msgs::ExpandOneRequest &&req) { break; } out_edges = out_edges_result.GetValue(); - - edges.reserve(in_edges.size() + out_edges.size()); - edges.insert(edges.end(), in_edges.begin(), in_edges.end()); - edges.insert(edges.end(), out_edges.begin(), out_edges.end()); break; } } @@ -781,65 +768,121 @@ msgs::ReadResponses ShardRsm::HandleRead(msgs::ExpandOneRequest &&req) { edges_with_specific_properties; if (!req.edge_properties) { - std::vector<std::tuple<msgs::VertexId, msgs::Gid, std::map<PropertyId, msgs::Value>>> ret; - ret.reserve(edges.size()); + std::vector<std::tuple<msgs::VertexId, msgs::Gid, std::map<PropertyId, msgs::Value>>> ret_in; + ret_in.reserve(in_edges.size()); + std::vector<std::tuple<msgs::VertexId, msgs::Gid, std::map<PropertyId, msgs::Value>>> ret_out; + ret_out.reserve(out_edges.size()); - for (const auto &edge : edges) { + for (const auto &edge : in_edges) { std::tuple<msgs::VertexId, msgs::Gid, std::map<PropertyId, msgs::Value>> ret_tuple; - msgs::Label label1 = {.id = edge.FromVertex().primary_label}; - msgs::VertexId vertex1 = std::make_pair(label1, ConvertValueVector(edge.FromVertex().primary_key)); - msgs::Label label2 = {.id = edge.ToVertex().primary_label}; - msgs::VertexId vertex2 = std::make_pair(label2, ConvertValueVector(edge.ToVertex().primary_key)); + msgs::Label label; + label.id = edge.FromVertex().primary_label; + msgs::VertexId other_vertex = std::make_pair(label, ConvertValueVector(edge.FromVertex().primary_key)); - auto other_vertex = vertex2; - - // Figure out which VertexId should be stored in the tuple - // TODO(gvolfing) overload operator==() for msgs::VertexId - // auto int1 = source_vertex.id.first.id.AsUint(); - // auto int2 = vertex1.first.id.AsUint(); - - // auto other_vertex = ((int1 == int2) && (ConvertPropertyVector(source_vertex.id.second) == - // ConvertPropertyVector(vertex1.second))) ? vertex2 : vertex1; auto other_vertex = vertex2; const auto &edge_props_var = get_edge_properties(edge); - auto edge_props = std::get<std::map<PropertyId, msgs::Value>>(edge_props_var); msgs::Gid gid = edge.Gid().AsUint(); ret_tuple = {other_vertex, gid, edge_props}; - ret.push_back(ret_tuple); + ret_in.push_back(ret_tuple); + } + + for (const auto &edge : out_edges) { + std::tuple<msgs::VertexId, msgs::Gid, std::map<PropertyId, msgs::Value>> ret_tuple; + + msgs::Label label; + label.id = edge.FromVertex().primary_label; + msgs::VertexId other_vertex = std::make_pair(label, ConvertValueVector(edge.ToVertex().primary_key)); + + const auto &edge_props_var = get_edge_properties(edge); + auto edge_props = std::get<std::map<PropertyId, msgs::Value>>(edge_props_var); + msgs::Gid gid = edge.Gid().AsUint(); + + ret_tuple = {other_vertex, gid, edge_props}; + ret_out.push_back(ret_tuple); } // Set one of the options to the actual datastructure and the otherone to nullopt - edges_with_all_properties = ret; + switch (req.direction) { + case msgs::EdgeDirection::OUT: { + edges_with_all_properties = ret_out; + break; + } + case msgs::EdgeDirection::IN: { + edges_with_all_properties = ret_in; + break; + } + case msgs::EdgeDirection::BOTH: { + std::vector<std::tuple<msgs::VertexId, msgs::Gid, std::map<PropertyId, msgs::Value>>> ret; + ret.resize(ret_out.size() + ret_in.size()); + ret.insert(ret.end(), ret_in.begin(), ret_in.end()); + ret.insert(ret.end(), ret_out.begin(), ret_out.end()); + + edges_with_all_properties = ret; + break; + } + } edges_with_specific_properties = {}; + } else { // when user specifies specific properties, its enough to return just a vector - std::vector<std::tuple<msgs::VertexId, msgs::Gid, std::vector<msgs::Value>>> ret; + std::vector<std::tuple<msgs::VertexId, msgs::Gid, std::vector<msgs::Value>>> ret_in; + ret_in.reserve(in_edges.size()); + std::vector<std::tuple<msgs::VertexId, msgs::Gid, std::vector<msgs::Value>>> ret_out; + ret_out.reserve(out_edges.size()); - for (const auto &edge : edges) { - std::tuple<msgs::VertexId, msgs::Gid, std::map<PropertyId, msgs::Value>> ret_tuple; - msgs::Label label1 = {.id = edge.FromVertex().primary_label}; - msgs::VertexId vertex1 = std::make_pair(label1, ConvertValueVector(edge.FromVertex().primary_key)); + for (const auto &edge : in_edges) { + std::tuple<msgs::VertexId, msgs::Gid, std::vector<msgs::Value>> ret_tuple; - msgs::Label label2 = {.id = edge.ToVertex().primary_label}; - msgs::VertexId vertex2 = std::make_pair(label2, ConvertValueVector(edge.ToVertex().primary_key)); - - auto other_vertex = vertex2; - - // Figure out which VertexId should be stored in the tuple - // TODO(gvolfing) overload operator==() for msgs::VertexId + msgs::Label label; + label.id = edge.FromVertex().primary_label; + msgs::VertexId other_vertex = std::make_pair(label, ConvertValueVector(edge.FromVertex().primary_key)); const auto &edge_props_var = get_edge_properties(edge); auto edge_props = std::get<std::vector<msgs::Value>>(edge_props_var); msgs::Gid gid = edge.Gid().AsUint(); - ret.push_back({other_vertex, gid, edge_props}); + ret_tuple = {other_vertex, gid, edge_props}; + ret_in.push_back(ret_tuple); + } + + for (const auto &edge : out_edges) { + std::tuple<msgs::VertexId, msgs::Gid, std::vector<msgs::Value>> ret_tuple; + + msgs::Label label; + label.id = edge.FromVertex().primary_label; + msgs::VertexId other_vertex = std::make_pair(label, ConvertValueVector(edge.ToVertex().primary_key)); + + const auto &edge_props_var = get_edge_properties(edge); + auto edge_props = std::get<std::vector<msgs::Value>>(edge_props_var); + msgs::Gid gid = edge.Gid().AsUint(); + + ret_tuple = {other_vertex, gid, edge_props}; + ret_out.push_back(ret_tuple); } // Set one of the options to the actual datastructure and the otherone to nullopt + switch (req.direction) { + case msgs::EdgeDirection::OUT: { + edges_with_specific_properties = ret_out; + break; + } + case msgs::EdgeDirection::IN: { + edges_with_specific_properties = ret_in; + break; + } + case msgs::EdgeDirection::BOTH: { + std::vector<std::tuple<msgs::VertexId, msgs::Gid, std::vector<msgs::Value>>> ret; + ret.resize(ret_out.size() + ret_in.size()); + ret.insert(ret.end(), ret_in.begin(), ret_in.end()); + ret.insert(ret.end(), ret_out.begin(), ret_out.end()); + + edges_with_specific_properties = ret; + break; + } + } edges_with_all_properties = {}; - edges_with_specific_properties = ret; } // Fill up current row.