Add InDegree and OutDegree in O(1) (#1217)
This commit is contained in:
parent
312d01bd0c
commit
d9464c6ffd
@ -367,6 +367,10 @@ inline mgp_map_item *map_items_iterator_next(mgp_map_items_iterator *it) {
|
|||||||
|
|
||||||
inline mgp_vertex_id vertex_get_id(mgp_vertex *v) { return MgInvoke<mgp_vertex_id>(mgp_vertex_get_id, v); }
|
inline mgp_vertex_id vertex_get_id(mgp_vertex *v) { return MgInvoke<mgp_vertex_id>(mgp_vertex_get_id, v); }
|
||||||
|
|
||||||
|
inline size_t vertex_get_in_degree(mgp_vertex *v) { return MgInvoke<size_t>(mgp_vertex_get_in_degree, v); }
|
||||||
|
|
||||||
|
inline size_t vertex_get_out_degree(mgp_vertex *v) { return MgInvoke<size_t>(mgp_vertex_get_out_degree, v); }
|
||||||
|
|
||||||
inline mgp_vertex *vertex_copy(mgp_vertex *v, mgp_memory *memory) {
|
inline mgp_vertex *vertex_copy(mgp_vertex *v, mgp_memory *memory) {
|
||||||
return MgInvoke<mgp_vertex *>(mgp_vertex_copy, v, memory);
|
return MgInvoke<mgp_vertex *>(mgp_vertex_copy, v, memory);
|
||||||
}
|
}
|
||||||
|
@ -647,6 +647,12 @@ struct mgp_vertex_id {
|
|||||||
/// Get the ID of given vertex.
|
/// Get the ID of given vertex.
|
||||||
enum mgp_error mgp_vertex_get_id(struct mgp_vertex *v, struct mgp_vertex_id *result);
|
enum mgp_error mgp_vertex_get_id(struct mgp_vertex *v, struct mgp_vertex_id *result);
|
||||||
|
|
||||||
|
/// Get the in degree of given vertex.
|
||||||
|
enum mgp_error mgp_vertex_get_in_degree(struct mgp_vertex *v, size_t *result);
|
||||||
|
|
||||||
|
/// Get the out degree of given vertex.
|
||||||
|
enum mgp_error mgp_vertex_get_out_degree(struct mgp_vertex *v, size_t *result);
|
||||||
|
|
||||||
/// Result is non-zero if the vertex can be modified.
|
/// Result is non-zero if the vertex can be modified.
|
||||||
/// The mutability of the vertex is the same as the graph which it is part of. If a vertex is immutable, then edges
|
/// The mutability of the vertex is the same as the graph which it is part of. If a vertex is immutable, then edges
|
||||||
/// cannot be created or deleted, properties and labels cannot be set or removed and all of the returned edges will be
|
/// cannot be created or deleted, properties and labels cannot be set or removed and all of the returned edges will be
|
||||||
|
@ -752,6 +752,12 @@ class Node {
|
|||||||
/// @brief returns the string representation
|
/// @brief returns the string representation
|
||||||
const std::string ToString() const;
|
const std::string ToString() const;
|
||||||
|
|
||||||
|
/// @brief returns the in degree of a node
|
||||||
|
inline size_t InDegree() const;
|
||||||
|
|
||||||
|
/// @brief returns the out degree of a node
|
||||||
|
inline size_t OutDegree() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
mgp_vertex *ptr_;
|
mgp_vertex *ptr_;
|
||||||
};
|
};
|
||||||
@ -2790,6 +2796,10 @@ inline const std::string Node::ToString() const {
|
|||||||
return "(id: " + std::to_string(Id().AsInt()) + labels + ", properties: {" + properties + "})";
|
return "(id: " + std::to_string(Id().AsInt()) + labels + ", properties: {" + properties + "})";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline size_t Node::InDegree() const { return mgp::vertex_get_in_degree(ptr_); }
|
||||||
|
|
||||||
|
inline size_t Node::OutDegree() const { return mgp::vertex_get_out_degree(ptr_); }
|
||||||
|
|
||||||
// Relationship:
|
// Relationship:
|
||||||
|
|
||||||
inline Relationship::Relationship(mgp_edge *ptr) : ptr_(mgp::MemHandlerCallback(edge_copy, ptr)) {}
|
inline Relationship::Relationship(mgp_edge *ptr) : ptr_(mgp::MemHandlerCallback(edge_copy, ptr)) {}
|
||||||
|
@ -242,6 +242,10 @@ class SubgraphVertexAccessor final {
|
|||||||
|
|
||||||
storage::Gid Gid() const noexcept { return impl_.Gid(); }
|
storage::Gid Gid() const noexcept { return impl_.Gid(); }
|
||||||
|
|
||||||
|
storage::Result<size_t> InDegree(storage::View view) const { return impl_.InDegree(view); }
|
||||||
|
|
||||||
|
storage::Result<size_t> OutDegree(storage::View view) const { return impl_.OutDegree(view); }
|
||||||
|
|
||||||
storage::Result<storage::PropertyValue> SetProperty(storage::PropertyId key, const storage::PropertyValue &value) {
|
storage::Result<storage::PropertyValue> SetProperty(storage::PropertyId key, const storage::PropertyValue &value) {
|
||||||
return impl_.SetProperty(key, value);
|
return impl_.SetProperty(key, value);
|
||||||
}
|
}
|
||||||
|
@ -1605,6 +1605,48 @@ mgp_error mgp_vertex_get_id(mgp_vertex *v, mgp_vertex_id *result) {
|
|||||||
result);
|
result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mgp_error mgp_vertex_get_in_degree(struct mgp_vertex *v, size_t *result) {
|
||||||
|
return WrapExceptions(
|
||||||
|
[v]() -> size_t {
|
||||||
|
auto maybe_in_degree = std::visit([v](const auto &impl) { return impl.InDegree(v->graph->view); }, v->impl);
|
||||||
|
if (maybe_in_degree.HasError()) {
|
||||||
|
switch (maybe_in_degree.GetError()) {
|
||||||
|
case memgraph::storage::Error::DELETED_OBJECT:
|
||||||
|
throw DeletedObjectException{"Cannot get the degree of a deleted vertex!"};
|
||||||
|
case memgraph::storage::Error::NONEXISTENT_OBJECT:
|
||||||
|
LOG_FATAL("Query modules shouldn't have access to nonexistent objects when getting vertex degree!");
|
||||||
|
case memgraph::storage::Error::PROPERTIES_DISABLED:
|
||||||
|
case memgraph::storage::Error::VERTEX_HAS_EDGES:
|
||||||
|
case memgraph::storage::Error::SERIALIZATION_ERROR:
|
||||||
|
LOG_FATAL("Unexpected error when getting vertex degree.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return *maybe_in_degree;
|
||||||
|
},
|
||||||
|
result);
|
||||||
|
}
|
||||||
|
|
||||||
|
mgp_error mgp_vertex_get_out_degree(struct mgp_vertex *v, size_t *result) {
|
||||||
|
return WrapExceptions(
|
||||||
|
[v]() -> size_t {
|
||||||
|
auto maybe_out_degree = std::visit([v](const auto &impl) { return impl.OutDegree(v->graph->view); }, v->impl);
|
||||||
|
if (maybe_out_degree.HasError()) {
|
||||||
|
switch (maybe_out_degree.GetError()) {
|
||||||
|
case memgraph::storage::Error::DELETED_OBJECT:
|
||||||
|
throw DeletedObjectException{"Cannot get the degree of a deleted vertex!"};
|
||||||
|
case memgraph::storage::Error::NONEXISTENT_OBJECT:
|
||||||
|
LOG_FATAL("Query modules shouldn't have access to nonexistent objects when getting vertex degree!");
|
||||||
|
case memgraph::storage::Error::PROPERTIES_DISABLED:
|
||||||
|
case memgraph::storage::Error::VERTEX_HAS_EDGES:
|
||||||
|
case memgraph::storage::Error::SERIALIZATION_ERROR:
|
||||||
|
LOG_FATAL("Unexpected error when getting vertex degree.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return *maybe_out_degree;
|
||||||
|
},
|
||||||
|
result);
|
||||||
|
}
|
||||||
|
|
||||||
mgp_error mgp_vertex_underlying_graph_is_mutable(mgp_vertex *v, int *result) {
|
mgp_error mgp_vertex_underlying_graph_is_mutable(mgp_vertex *v, int *result) {
|
||||||
return mgp_graph_is_mutable(v->graph, result);
|
return mgp_graph_is_mutable(v->graph, result);
|
||||||
}
|
}
|
||||||
|
@ -689,3 +689,25 @@ TYPED_TEST(CppApiTestFixture, TestValueToString) {
|
|||||||
"(id: 2, :Label1:Label2, properties: {})-[type: Loves, id: 0, properties: {key: property}]->(id: 3, properties: "
|
"(id: 2, :Label1:Label2, properties: {})-[type: Loves, id: 0, properties: {key: property}]->(id: 3, properties: "
|
||||||
"{key: node_property, key2: node_property2})-[type: Loves2, id: 1, properties: {}]->(id: 4, properties: {})");
|
"{key: node_property, key2: node_property2})-[type: Loves2, id: 1, properties: {}]->(id: 4, properties: {})");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TYPED_TEST(CppApiTestFixture, TestInAndOutDegrees) {
|
||||||
|
mgp_graph raw_graph = this->CreateGraph(memgraph::storage::View::NEW);
|
||||||
|
auto graph = mgp::Graph(&raw_graph);
|
||||||
|
auto node_1 = graph.CreateNode();
|
||||||
|
auto node_2 = graph.CreateNode();
|
||||||
|
auto node_3 = graph.CreateNode();
|
||||||
|
auto relationship = graph.CreateRelationship(node_1, node_2, "Relationship1");
|
||||||
|
auto relationship2 = graph.CreateRelationship(node_1, node_2, "Relationship2");
|
||||||
|
auto relationship3 = graph.CreateRelationship(node_1, node_2, "Relationship3");
|
||||||
|
auto relationship4 = graph.CreateRelationship(node_1, node_2, "Relationship4");
|
||||||
|
auto relationship5 = graph.CreateRelationship(node_1, node_3, "Relationship5");
|
||||||
|
auto relationship6 = graph.CreateRelationship(node_1, node_3, "Relationship6");
|
||||||
|
|
||||||
|
ASSERT_EQ(node_1.OutDegree(), 6);
|
||||||
|
ASSERT_EQ(node_2.InDegree(), 4);
|
||||||
|
ASSERT_EQ(node_3.InDegree(), 2);
|
||||||
|
|
||||||
|
ASSERT_EQ(node_1.InDegree(), 0);
|
||||||
|
ASSERT_EQ(node_2.OutDegree(), 0);
|
||||||
|
ASSERT_EQ(node_3.OutDegree(), 0);
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user