use std::collections::{hash_map::DefaultHasher, BTreeMap, BTreeSet};
use std::hash::{Hash, Hasher};
#[derive(Debug, Default, Clone, PartialEq, Eq)]
pub struct GraphStats {
pub node_count: usize,
pub relationship_count: usize,
pub nodes_by_label: BTreeMap<String, usize>,
pub relationships_by_type: BTreeMap<String, usize>,
pub node_distinct_values: BTreeMap<(String, String), usize>,
pub relationship_distinct_values: BTreeMap<(String, String), usize>,
pub node_range_indexes: BTreeSet<(String, String)>,
pub relationship_range_indexes: BTreeSet<(String, String)>,
pub node_text_indexes: BTreeSet<(String, String)>,
pub relationship_text_indexes: BTreeSet<(String, String)>,
pub node_point_indexes: BTreeSet<(String, String)>,
pub relationship_point_indexes: BTreeSet<(String, String)>,
pub node_vector_indexes: BTreeSet<(String, String)>,
pub relationship_vector_indexes: BTreeSet<(String, String)>,
}
impl GraphStats {
pub fn estimate_node_property_equality(&self, label: &str, property: &str) -> Option<u64> {
let total = self.nodes_by_label.get(label).copied()? as u64;
let distinct = self
.node_distinct_values
.get(&(label.to_string(), property.to_string()))
.copied()
.unwrap_or(1)
.max(1) as u64;
Some(total.div_ceil(distinct))
}
pub fn label_count(&self, label: &str) -> Option<u64> {
self.nodes_by_label.get(label).copied().map(|c| c as u64)
}
pub fn relationship_type_count(&self, rel_type: &str) -> Option<u64> {
self.relationships_by_type
.get(rel_type)
.copied()
.map(|c| c as u64)
}
pub fn fingerprint(&self) -> u64 {
let mut hasher = DefaultHasher::new();
self.node_count.hash(&mut hasher);
self.relationship_count.hash(&mut hasher);
self.nodes_by_label.hash(&mut hasher);
self.relationships_by_type.hash(&mut hasher);
self.node_distinct_values.hash(&mut hasher);
self.relationship_distinct_values.hash(&mut hasher);
self.node_range_indexes.hash(&mut hasher);
self.relationship_range_indexes.hash(&mut hasher);
self.node_text_indexes.hash(&mut hasher);
self.relationship_text_indexes.hash(&mut hasher);
self.node_point_indexes.hash(&mut hasher);
self.relationship_point_indexes.hash(&mut hasher);
self.node_vector_indexes.hash(&mut hasher);
self.relationship_vector_indexes.hash(&mut hasher);
hasher.finish()
}
pub fn has_node_range_index(&self, label: &str, property: &str) -> bool {
self.node_range_indexes
.contains(&(label.to_owned(), property.to_owned()))
}
pub fn has_node_text_index(&self, label: &str, property: &str) -> bool {
self.node_text_indexes
.contains(&(label.to_owned(), property.to_owned()))
}
pub fn has_node_point_index(&self, label: &str, property: &str) -> bool {
self.node_point_indexes
.contains(&(label.to_owned(), property.to_owned()))
}
pub fn has_relationship_range_index(&self, rel_type: &str, property: &str) -> bool {
self.relationship_range_indexes
.contains(&(rel_type.to_owned(), property.to_owned()))
}
pub fn has_relationship_text_index(&self, rel_type: &str, property: &str) -> bool {
self.relationship_text_indexes
.contains(&(rel_type.to_owned(), property.to_owned()))
}
pub fn has_relationship_point_index(&self, rel_type: &str, property: &str) -> bool {
self.relationship_point_indexes
.contains(&(rel_type.to_owned(), property.to_owned()))
}
pub fn has_node_vector_index(&self, label: &str, property: &str) -> bool {
self.node_vector_indexes
.contains(&(label.to_owned(), property.to_owned()))
}
pub fn has_relationship_vector_index(&self, rel_type: &str, property: &str) -> bool {
self.relationship_vector_indexes
.contains(&(rel_type.to_owned(), property.to_owned()))
}
}