use std::collections::HashMap;
use std::sync::Arc;
use serde_json::Value;
use crate::generated::admin_api_core::GeneratedAdminApi;
use edgebase_core::error::Error;
use edgebase_core::http_client::HttpClient;
pub struct VectorizeClient {
http: Arc<HttpClient>,
pub(crate) index: String,
}
impl VectorizeClient {
pub(crate) fn new(http: Arc<HttpClient>, index: &str) -> Self {
Self {
http,
index: index.to_string(),
}
}
fn core(&self) -> GeneratedAdminApi<'_> {
GeneratedAdminApi::new(&self.http)
}
pub async fn upsert(&self, vectors: &[Value]) -> Result<Value, Error> {
let body = serde_json::json!({"action": "upsert", "vectors": vectors});
self.core().vectorize_operation(&self.index, &body).await
}
pub async fn insert(&self, vectors: &[Value]) -> Result<Value, Error> {
let body = serde_json::json!({"action": "insert", "vectors": vectors});
self.core().vectorize_operation(&self.index, &body).await
}
pub async fn search(
&self,
vector: &[f64],
top_k: usize,
filter: Option<&Value>,
namespace: Option<&str>,
return_values: Option<bool>,
return_metadata: Option<&str>,
) -> Result<Vec<HashMap<String, Value>>, Error> {
let mut body = serde_json::json!({
"action": "search",
"vector": vector,
"topK": top_k,
});
if let Some(f) = filter {
body["filter"] = f.clone();
}
if let Some(ns) = namespace {
body["namespace"] = serde_json::json!(ns);
}
if let Some(rv) = return_values {
body["returnValues"] = serde_json::json!(rv);
}
if let Some(rm) = return_metadata {
body["returnMetadata"] = serde_json::json!(rm);
}
let res: Value = self.core().vectorize_operation(&self.index, &body).await?;
extract_matches(&res)
}
pub async fn query_by_id(
&self,
vector_id: &str,
top_k: usize,
filter: Option<&Value>,
namespace: Option<&str>,
return_values: Option<bool>,
return_metadata: Option<&str>,
) -> Result<Vec<HashMap<String, Value>>, Error> {
let mut body = serde_json::json!({
"action": "queryById",
"vectorId": vector_id,
"topK": top_k,
});
if let Some(f) = filter {
body["filter"] = f.clone();
}
if let Some(ns) = namespace {
body["namespace"] = serde_json::json!(ns);
}
if let Some(rv) = return_values {
body["returnValues"] = serde_json::json!(rv);
}
if let Some(rm) = return_metadata {
body["returnMetadata"] = serde_json::json!(rm);
}
let res: Value = self.core().vectorize_operation(&self.index, &body).await?;
extract_matches(&res)
}
pub async fn get_by_ids(&self, ids: &[&str]) -> Result<Vec<HashMap<String, Value>>, Error> {
let body = serde_json::json!({"action": "getByIds", "ids": ids});
let res: Value = self.core().vectorize_operation(&self.index, &body).await?;
if let Some(vectors) = res.get("vectors").and_then(|v| v.as_array()) {
Ok(vectors
.iter()
.filter_map(|v| {
v.as_object()
.map(|o| o.iter().map(|(k, v)| (k.clone(), v.clone())).collect())
})
.collect())
} else {
Ok(vec![])
}
}
pub async fn delete(&self, ids: &[&str]) -> Result<Value, Error> {
let body = serde_json::json!({"action": "delete", "ids": ids});
self.core().vectorize_operation(&self.index, &body).await
}
pub async fn describe(&self) -> Result<Value, Error> {
let body = serde_json::json!({"action": "describe"});
self.core().vectorize_operation(&self.index, &body).await
}
}
fn extract_matches(res: &Value) -> Result<Vec<HashMap<String, Value>>, Error> {
if let Some(matches) = res.get("matches").and_then(|v| v.as_array()) {
Ok(matches
.iter()
.filter_map(|v| {
v.as_object()
.map(|o| o.iter().map(|(k, v)| (k.clone(), v.clone())).collect())
})
.collect())
} else {
Ok(vec![])
}
}