🧠 vector-xlite
VectorXLite — A fast, lightweight vector search with payload support and SQL-based filtering.
Crate : https://crates.io/crates/vector_xlite
This demonstrates how to use the vector_xlite crate to:
- Create a collection with vector embeddings and optional payload data.
- Insert and manage vectors along with associated metadata.
- Perform fast vector similarity search (e.g., Cosine, Dot, or L2 distance).
- Filter and query payloads using standard SQL alongside vector search.
🧱 Step-by-Step Breakdown
1. Create the Collection
let config = CollectionConfigBuilder::default()
.collection_name("person")
.distance(DistanceFunction::Cosine)
.vector_dimension(4)
.payload_table_schema("create table person (rowid integer primary key, name text)")
.build()
.unwrap();
vs.create_collection(config).unwrap();
This defines:
- collection_name — logical name for your vector data
- distance — similarity metric (Cosine, L2, or Dot)
- vector_dimension — length of the embedding vector
- payload_table_schema — SQL used to store associated metadata
2. Insert Vector Points
Each vector point includes an id, vector embedding, and an SQL payload insertion query.
let point = InsertPoint::builder()
.collection_name("person")
.id(1)
.vector(vec![1.0, 2.0, 3.0, 4.0])
.payload_insert_query("insert into person(rowid, name) values (?1, 'Alice')")
.build()
.unwrap();
vs.insert(point).unwrap();
Use ?1 as a placeholder to bind the vector ID in your SQL statement.
3. Search for Similar Vectors
Perform a similarity search with a given vector and get top matches:
let search_point = SearchPoint::builder()
.collection_name("person")
.vector(vec![7.0, 8.0, 9.0, 2.0])
.top_k(10)
.payload_search_query("select * from person")
.build()
.unwrap();
let results = vs.search(search_point).unwrap();
This fetches the top-K most similar vectors from the collection, along with their payloads.
🚀 Console Example — vector_xlite
A minimal Rust example showing how to use the vector_xlite crate via the included example binary.
The example opens an in-memory SQLite connection, registers the VectorXLite extension, creates a collection, inserts several vector points with payloads, and performs a vector search.
🧩 Prerequisites
- Rust (latest stable)
- SQLite (with extension loading enabled)
▶️ Running the Example
From the repository root:
cd example
cargo run
Or run the specific package directly:
cargo run -p example
📘 Full Example
This example corresponds to the contents of src/main.rs inside the example crate:
use vector_xlite::{
types::{SearchPoint, CollectionConfigBuilder, InsertPoint, DistanceFunction},
VectorXLite,
};
use rusqlite::Connection;
fn main() {
let sqlite_connection = Connection::open_in_memory().unwrap();
let vs = VectorXLite::new(sqlite_connection).unwrap();
let config = CollectionConfigBuilder::default()
.collection_name("person")
.distance(DistanceFunction::Cosine)
.vector_dimension(4)
.payload_table_schema("create table person (rowid integer primary key, name text)")
.build()
.unwrap();
match vs.create_collection(config) {
Ok(_) => {
let points = vec![
InsertPoint::builder()
.collection_name("person")
.id(1)
.vector(vec![1.0, 2.0, 3.0, 4.0])
.payload_insert_query("insert into person(rowid, name) values (?1, 'Alice')")
.build()
.unwrap(),
InsertPoint::builder()
.collection_name("person")
.id(2)
.vector(vec![4.0, 5.0, 6.0, 4.0])
.payload_insert_query("insert into person(name, rowid) values ('Bob', ?1)")
.build()
.unwrap(),
InsertPoint::builder()
.collection_name("person")
.id(3)
.vector(vec![7.0, 8.0, 9.0, 4.0])
.payload_insert_query("insert into person(name) values ('Charlie')")
.build()
.unwrap(),
InsertPoint::builder()
.collection_name("person")
.id(5)
.vector(vec![17.0, 11.0, 9.0, 4.0])
.payload_insert_query("insert into person(name) values ('David')")
.build()
.unwrap(),
];
for point in points {
vs.insert(point).unwrap();
}
let search_point = SearchPoint::builder()
.collection_name("person")
.vector(vec![7.0, 8.0, 9.0, 2.0])
.top_k(10)
.payload_search_query("select * from person")
.build()
.unwrap();
let results = vs.search(search_point).unwrap();
println!("🔍 Search results: {:?}", results);
}
Err(e) => println!("❌ Error creating collection: {:?}", e),
}
}
Details Example
use std::sync::Arc;
use rusqlite::Connection;
use vector_xlite::{VectorXLite, types::*};
pub fn run_complex_example(vlite: &VectorXLite, sqlite_conn: Arc<Connection>) {
let create_authors_table = r#"
create table authors (
id integer primary key,
name text not null,
bio text
);
"#;
sqlite_conn
.execute(create_authors_table, [])
.expect("Failed to create authors table");
let author_inserts = vec![
"insert into authors(id, name, bio) values (1, 'Alice', 'Writer of whimsical fantasy worlds')",
"insert into authors(id, name, bio) values (2, 'Bob', 'Short story enthusiast and poet')",
"insert into authors(id, name, bio) values (3, 'Carol', 'Sci-fi novelist exploring deep space themes')",
];
for q in author_inserts {
sqlite_conn.execute(q, []).unwrap();
}
let story_collection_config = CollectionConfigBuilder::default()
.collection_name("story_advanced")
.distance(DistanceFunction::Cosine)
.vector_dimension(8)
.payload_table_schema(
r#"
create table story_advanced (
rowid integer primary key,
author_id integer,
title text,
content text,
tags json,
published_at text default (datetime('now')),
rating real
);
"#,
)
.build()
.unwrap();
match vlite.create_collection(story_collection_config) {
Ok(_) => {
let points = vec![
InsertPoint::builder()
.collection_name("story_advanced")
.id(101)
.vector(vec![0.11, 0.22, 0.33, 0.44, 0.55, 0.66, 0.77, 0.88])
.payload_insert_query(r#"
insert into story_advanced(rowid, author_id, title, content, tags, rating)
values (?1, 1, 'Dreaming in Colors', 'Once upon a vibrant night...', '["fantasy","dreams"]', 4.8)
"#)
.build()
.unwrap(),
InsertPoint::builder()
.collection_name("story_advanced")
.id(102)
.vector(vec![0.9, 0.8, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6])
.payload_insert_query(r#"
insert into story_advanced(rowid, author_id, title, content, tags, rating)
values (?1, 2, 'The Quiet Storm', 'Thunder rolled over the valley...', '["drama","short","weather"]', 4.2)
"#)
.build()
.unwrap(),
InsertPoint::builder()
.collection_name("story_advanced")
.id(103)
.vector(vec![0.05, 0.25, 0.45, 0.65, 0.85, 0.15, 0.35, 0.55])
.payload_insert_query(r#"
insert into story_advanced(rowid, author_id, title, content, tags, rating)
values (?1, 3, 'Stars Beneath the Waves', 'A galaxy reflected in the ocean depths...', '["sci-fi","ocean","space"]', 4.9)
"#)
.build()
.unwrap(),
];
for point in points {
vlite.insert(point.clone()).unwrap();
}
println!("✅ Inserted complex story points into 'story_advanced' collection.");
let search_point = SearchPoint::builder()
.collection_name("story_advanced")
.vector(vec![0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8])
.top_k(5)
.payload_search_query(
r#"
select
s.rowid,
s.title,
s.rating,
a.name as author,
s.tags,
s.published_at
from story_advanced s
join authors a on a.id = s.author_id
where s.rating > 4.0
and json_extract(s.tags, '$[0]') != 'drama'
order by s.rating desc
"#,
)
.build()
.unwrap();
let results = vlite.search(search_point).unwrap();
println!("\n🚀 Advanced Story Search Results:\n{:#?}", results);
}
Err(e) => println!("❌ Error creating advanced story collection: {:?}", e),
}
}
🧩 API Reference (Summary)
VectorXLite::new(conn: rusqlite::Connection)
Initializes VectorXLite on the given SQLite connection.
CollectionConfigBuilder
| Method |
Description |
.collection_name(&str) |
Sets the logical collection name |
.distance(DistanceFunction) |
Sets similarity metric (Cosine, L2, or Dot) |
.vector_dimension(usize) |
Defines vector dimensionality |
.payload_table_schema(&str) |
SQL to create payload table |
.build() |
Builds final config |
InsertPoint Builder
| Method |
Description |
.collection_name(&str) |
Collection to insert into |
.id(i64) |
Unique point ID |
.vector(Vec<f32>) |
Vector embedding |
.payload_insert_query(&str) |
SQL to insert payload data |
SearchPoint Builder
| Method |
Description |
.collection_name(&str) |
Collection to search |
.vector(Vec<f32>) |
Query vector |
.top_k(usize) |
Number of top results |
.payload_search_query(&str) |
SQL query for payloads |
🛠 Troubleshooting
Persistent storage
Replace Connection::open_in_memory() with a file-backed connection:
let conn = Connection::open("vectors.db")?;