use std::sync::Once;
use zvec_rust::*;
static INIT: Once = Once::new();
fn ensure_initialized() {
INIT.call_once(|| {
initialize(None).expect("failed to initialize zvec");
});
}
#[test]
fn test_exact_string_filter_returns_matching_rows() {
ensure_initialized();
let tmp_dir = tempfile::tempdir().unwrap();
let dir = tmp_dir.path().join("zvec_data");
let schema = CollectionSchema::builder("string_filter_test")
.add_field(FieldSchema::new("id", DataType::String, false, 0).unwrap())
.add_indexed_field(
"name",
DataType::String,
IndexParams::invert(false, false).unwrap(),
)
.add_vector_field(
"embedding",
DataType::VectorFp32,
2,
IndexParams::hnsw(MetricType::Cosine, 16, 200).unwrap(),
)
.build()
.expect("failed to build schema");
let collection = Collection::create_and_open(dir.to_str().unwrap(), &schema, None)
.expect("failed to create collection");
let names = ["alice", "bob", "alice", "carol"];
let mut docs = Vec::new();
for (i, name) in names.iter().enumerate() {
let mut doc = Doc::new().unwrap();
doc.set_pk(&format!("pk_{}", i));
doc.add_string("id", &format!("pk_{}", i)).unwrap();
doc.add_string("name", name).unwrap();
doc.add_vector_f32("embedding", &[0.1, 0.2]).unwrap();
docs.push(doc);
}
let doc_refs: Vec<&Doc> = docs.iter().collect();
let result = collection.insert(&doc_refs).unwrap();
assert_eq!(result.success_count, names.len() as u64);
collection.flush().expect("flush before filter query");
let mut query = SearchQuery::new("embedding", &[0.1, 0.2], names.len() as i32).unwrap();
query.set_filter("name = 'alice'").unwrap();
let results = collection.query(&query).unwrap();
assert_eq!(
results.len(),
2,
"exact string filter should return exactly the matching rows"
);
for doc in &results {
assert_eq!(
doc.get_string("name").unwrap().as_deref(),
Some("alice"),
"every returned row must match the filter"
);
}
}