use super::DirGraph;
use crate::datatypes::values::Value;
use crate::graph::schema::InternedKey;
use crate::graph::storage::GraphRead; use std::collections::HashMap;
impl DirGraph {
pub fn get_edge_type_counts(&self) -> HashMap<String, usize> {
{
let read = self.edge_type_counts_cache.read().unwrap();
if let Some(ref cached) = *read {
return cached.clone();
}
}
let mut counts: HashMap<InternedKey, usize> = HashMap::new();
for (_src, _tgt, conn_key) in self.graph.edge_endpoint_keys() {
*counts.entry(conn_key).or_insert(0) += 1;
}
let string_counts: HashMap<String, usize> = counts
.into_iter()
.map(|(k, v)| (self.interner.resolve(k).to_string(), v))
.collect();
let mut write = self.edge_type_counts_cache.write().unwrap();
*write = Some(string_counts.clone());
string_counts
}
pub(crate) fn invalidate_edge_type_counts_cache(&self) {
*self.edge_type_counts_cache.write().unwrap() = None;
*self.type_connectivity_cache.write().unwrap() = None;
}
pub fn property_ndv(&self, node_type: &str, property: &str) -> Option<usize> {
const MAX_SCAN: usize = 200_000;
let nodes = self.type_indices.get(node_type)?;
if nodes.is_empty() || nodes.len() > MAX_SCAN {
return None;
}
let key = (node_type.to_string(), property.to_string());
{
let read = self.property_ndv_cache.read().unwrap();
if read.0 == self.version {
if let Some(&ndv) = read.1.get(&key) {
return Some(ndv);
}
}
}
let mut seen: std::collections::HashSet<Value> = std::collections::HashSet::new();
for idx in nodes.iter() {
if let Some(node) = self.get_node(idx) {
if let Some(val) = node.get_property(property) {
seen.insert(val.into_owned());
}
}
}
let ndv = seen.len().max(1);
let mut write = self.property_ndv_cache.write().unwrap();
if write.0 != self.version {
write.1.clear();
write.0 = self.version;
}
write.1.insert(key, ndv);
Some(ndv)
}
pub fn has_edge_type_counts_cache(&self) -> bool {
self.edge_type_counts_cache.read().unwrap().is_some()
}
pub fn has_type_connectivity_cache(&self) -> bool {
self.type_connectivity_cache.read().unwrap().is_some()
}
}