use crate::parser::ParserTypeMarker;
use crate::{
parser::{
parse_falkor_enum, parse_raw_redis_value, redis_value_as_string,
redis_value_as_typed_string, redis_value_as_typed_string_vec, redis_value_as_vec,
type_val_from_value, SchemaParsable,
},
EntityType, FalkorDBError, FalkorValue, GraphSchema,
};
use std::collections::HashMap;
#[derive(Copy, Clone, Debug, Eq, PartialEq, strum::EnumString, strum::Display)]
#[strum(serialize_all = "UPPERCASE")]
pub enum IndexStatus {
#[strum(serialize = "OPERATIONAL")]
Active,
#[strum(serialize = "UNDER CONSTRUCTION")]
Pending,
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, strum::EnumString, strum::Display)]
#[strum(serialize_all = "UPPERCASE")]
pub enum IndexType {
Range,
Vector,
Fulltext,
}
fn parse_types_map(value: redis::Value) -> Result<HashMap<String, Vec<IndexType>>, FalkorDBError> {
type_val_from_value(value).and_then(|(type_marker, val)| {
if type_marker != ParserTypeMarker::Map {
return Err(FalkorDBError::ParsingMap);
}
let map_iter = val.into_map_iter().map_err(|_| FalkorDBError::ParsingMap)?;
let result = map_iter
.into_iter()
.map(|(key, val)| {
let key_str = redis_value_as_string(key)?;
let (val_type_marker, val) = type_val_from_value(val)?;
if val_type_marker != ParserTypeMarker::Array {
return Err(FalkorDBError::ParsingArray);
}
let val_vec = redis_value_as_vec(val)?;
let parsed_values = val_vec
.into_iter()
.flat_map(parse_falkor_enum::<IndexType>)
.collect::<Vec<_>>();
Ok((key_str, parsed_values))
})
.collect::<Result<HashMap<_, _>, FalkorDBError>>()?;
Ok(result)
})
}
#[derive(Clone, Debug, PartialEq)]
pub struct FalkorIndex {
pub entity_type: EntityType,
pub status: IndexStatus,
pub index_label: String,
pub fields: Vec<String>,
pub field_types: HashMap<String, Vec<IndexType>>,
pub language: String,
pub stopwords: Vec<String>,
pub info: HashMap<String, FalkorValue>,
}
impl SchemaParsable for FalkorIndex {
#[cfg_attr(
feature = "tracing",
tracing::instrument(name = "Parse Index", skip_all, level = "info")
)]
fn parse(
value: redis::Value,
graph_schema: &mut GraphSchema,
) -> Result<Self, FalkorDBError> {
let [label, fields, field_types, language, stopwords, entity_type, status, info] =
redis_value_as_vec(value).and_then(|as_vec| {
as_vec.try_into().map_err(|_| {
FalkorDBError::ParsingArrayToStructElementCount(
"Expected exactly 8 elements in index object",
)
})
})?;
Ok(Self {
entity_type: parse_falkor_enum(entity_type)?,
status: parse_falkor_enum(status)?,
index_label: redis_value_as_typed_string(label)?,
fields: redis_value_as_typed_string_vec(fields)?,
field_types: parse_types_map(field_types)?,
language: redis_value_as_typed_string(language)?,
stopwords: redis_value_as_typed_string_vec(stopwords)?,
info: parse_raw_redis_value(info, graph_schema).and_then(|val| val.into_map())?,
})
}
}