use selene_core::{Change, DbString, HnswIndexConfig, SchemaChange, SchemaVectorIndexKind};
use crate::graph::VectorIndexEntry;
use crate::{GraphError, GraphResult, Mutator, VectorIndexConfig, VectorIndexKind};
impl<'tx, 'g> Mutator<'tx, 'g> {
pub fn create_vector_index(
&mut self,
label: DbString,
property: DbString,
kind: VectorIndexKind,
dimension: u32,
) -> GraphResult<()> {
self.create_vector_index_named(label, property, kind, dimension, None)
}
pub fn create_vector_index_named(
&mut self,
label: DbString,
property: DbString,
kind: VectorIndexKind,
dimension: u32,
name: Option<DbString>,
) -> GraphResult<()> {
self.create_vector_index_named_with_config(label, property, kind, dimension, name, None)
}
pub fn create_vector_index_named_with_config(
&mut self,
label: DbString,
property: DbString,
kind: VectorIndexKind,
dimension: u32,
name: Option<DbString>,
hnsw_config: Option<HnswIndexConfig>,
) -> GraphResult<()> {
self.create_vector_index_named_with_configs(
label,
property,
kind,
dimension,
name,
VectorIndexConfig::new(hnsw_config, None),
)
}
pub fn create_vector_index_named_with_configs(
&mut self,
label: DbString,
property: DbString,
kind: VectorIndexKind,
dimension: u32,
name: Option<DbString>,
config: VectorIndexConfig,
) -> GraphResult<()> {
if self
.txn
.read()
.vector_index
.contains_key(&(label.clone(), property.clone()))
{
return Err(GraphError::VectorIndexAlreadyExists { label, property });
}
let index = crate::vector_index::build_vector_index_with_configs(
self.txn.read(),
label.clone(),
property.clone(),
kind,
dimension,
config,
)?;
let hnsw_config = index.hnsw_config();
let ivf_config = index.ivf_config();
let graph_id = self.txn.read().graph_id();
self.txn.guard_mut().vector_index.insert(
(label.clone(), property.clone()),
VectorIndexEntry::new(index, name.clone()),
);
self.txn.changes.push(Change::SchemaChanged {
graph: graph_id,
change: SchemaChange::VectorIndexCreated {
label,
property,
kind: schema_kind_from(kind),
dimension,
name,
hnsw_config,
ivf_config,
},
});
Ok(())
}
pub fn drop_vector_index(&mut self, label: DbString, property: DbString) -> GraphResult<()> {
if !self
.txn
.read()
.vector_index
.contains_key(&(label.clone(), property.clone()))
{
return Ok(());
}
let graph_id = self.txn.read().graph_id();
self.txn
.guard_mut()
.vector_index
.remove(&(label.clone(), property.clone()));
self.txn.changes.push(Change::SchemaChanged {
graph: graph_id,
change: SchemaChange::VectorIndexDropped { label, property },
});
Ok(())
}
}
const fn schema_kind_from(kind: VectorIndexKind) -> SchemaVectorIndexKind {
match kind {
VectorIndexKind::Flat => SchemaVectorIndexKind::Flat,
VectorIndexKind::HnswSquaredEuclidean => SchemaVectorIndexKind::HnswSquaredEuclidean,
VectorIndexKind::HnswCosine => SchemaVectorIndexKind::HnswCosine,
VectorIndexKind::HnswNegativeInnerProduct => {
SchemaVectorIndexKind::HnswNegativeInnerProduct
}
VectorIndexKind::IvfSquaredEuclidean => SchemaVectorIndexKind::IvfSquaredEuclidean,
VectorIndexKind::IvfCosine => SchemaVectorIndexKind::IvfCosine,
VectorIndexKind::IvfNegativeInnerProduct => SchemaVectorIndexKind::IvfNegativeInnerProduct,
VectorIndexKind::TurboQuantCosine => SchemaVectorIndexKind::TurboQuantCosine,
}
}
#[cfg(test)]
#[path = "vector_index/tests.rs"]
mod tests;