Skip to main content

velesdb_core/database/
graph_ops.rs

1//! Graph collection creation and retrieval operations.
2
3use crate::collection::GraphCollection;
4use crate::{CollectionType, DistanceMetric, Result};
5
6use super::Database;
7
8#[allow(deprecated)]
9impl Database {
10    /// Creates a new graph collection.
11    ///
12    /// # Errors
13    ///
14    /// Returns an error if a collection with the same name already exists.
15    #[allow(clippy::needless_pass_by_value)] // Public API — changing to &ref would be breaking.
16    pub fn create_graph_collection(
17        &self,
18        name: &str,
19        schema: crate::collection::GraphSchema,
20    ) -> Result<()> {
21        self.ensure_collection_name_available(name)?;
22        let path = self.data_dir.join(name);
23        let coll =
24            GraphCollection::create(path, name, None, DistanceMetric::Cosine, schema.clone())?;
25        self.register_graph_collection(name, &coll, None, DistanceMetric::Cosine, &schema);
26        Ok(())
27    }
28
29    /// Creates a new graph collection with node embeddings.
30    ///
31    /// Unlike [`create_graph_collection`](Self::create_graph_collection), this
32    /// variant configures a vector dimension and distance metric so that nodes
33    /// can store embeddings and support similarity search.
34    ///
35    /// # Errors
36    ///
37    /// Returns an error if a collection with the same name already exists.
38    #[allow(clippy::needless_pass_by_value)] // Public API — changing to &ref would be breaking.
39    pub fn create_graph_collection_with_embeddings(
40        &self,
41        name: &str,
42        schema: crate::collection::GraphSchema,
43        dimension: usize,
44        metric: DistanceMetric,
45    ) -> Result<()> {
46        self.ensure_collection_name_available(name)?;
47        let path = self.data_dir.join(name);
48        let coll = GraphCollection::create(path, name, Some(dimension), metric, schema.clone())?;
49        self.register_graph_collection(name, &coll, Some(dimension), metric, &schema);
50        Ok(())
51    }
52
53    /// Internal helper for `create_collection_typed` with `Graph` variant.
54    pub(super) fn create_graph_collection_from_type(
55        &self,
56        name: &str,
57        dimension: Option<usize>,
58        metric: DistanceMetric,
59        schema: &crate::collection::GraphSchema,
60    ) -> Result<()> {
61        self.ensure_collection_name_available(name)?;
62        let path = self.data_dir.join(name);
63        let coll = GraphCollection::create(path, name, dimension, metric, schema.clone())?;
64        self.register_graph_collection(name, &coll, dimension, metric, schema);
65        Ok(())
66    }
67
68    /// Registers a graph collection in both legacy and typed registries,
69    /// notifies the observer, and bumps the schema version.
70    fn register_graph_collection(
71        &self,
72        name: &str,
73        coll: &GraphCollection,
74        dimension: Option<usize>,
75        metric: DistanceMetric,
76        schema: &crate::collection::GraphSchema,
77    ) {
78        self.collections
79            .write()
80            .insert(name.to_string(), coll.inner.clone());
81        self.graph_colls
82            .write()
83            .insert(name.to_string(), coll.clone());
84
85        if let Some(ref obs) = self.observer {
86            let kind = CollectionType::Graph {
87                dimension,
88                metric,
89                schema: schema.clone(),
90            };
91            obs.on_collection_created(name, &kind);
92        }
93
94        self.schema_version
95            .fetch_add(1, std::sync::atomic::Ordering::Relaxed);
96    }
97
98    /// Returns a `GraphCollection` by name.
99    ///
100    /// Checks the typed registry first.  Falls back to opening from disk if the
101    /// collection was not registered in-memory (e.g. after a restart or when
102    /// the collection was auto-created by a graph handler).  The instance is
103    /// cached into the registry so subsequent calls are free.
104    ///
105    /// Returns `None` if the collection does not exist on disk.
106    #[must_use]
107    pub fn get_graph_collection(&self, name: &str) -> Option<GraphCollection> {
108        if let Some(c) = self.graph_colls.read().get(name).cloned() {
109            return Some(c);
110        }
111        self.open_graph_collection_from_disk(name)
112    }
113
114    /// Disk fallback for `get_graph_collection`.
115    fn open_graph_collection_from_disk(&self, name: &str) -> Option<GraphCollection> {
116        let cfg = self.read_collection_config(name)?;
117        cfg.graph_schema.as_ref()?;
118        let coll = GraphCollection::open(self.data_dir.join(name)).ok()?;
119        self.graph_colls
120            .write()
121            .insert(name.to_string(), coll.clone());
122        Some(coll)
123    }
124}