Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ strum = "0.24"
strum_macros = "0.24"
base64 = "0.21.0"
dashmap = "5.5.3"
lazy_static = "1.4"

[build-dependencies]
tonic-build = { version = "0.8.2", default-features = false, features = [
Expand Down
146 changes: 146 additions & 0 deletions examples/authentication.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
use milvus::client::{Client, ClientBuilder};
use milvus::error::Result;

#[tokio::main]
async fn main() -> Result<()> {
let client = ClientBuilder::new("http://localhost:19530")
.username("root")
.password("Milvus")
.build()
.await?;
//user test
user_test(&client).await?;
//role test
role_test(&client).await?;
//privilege test
privilege_test(&client).await?;
Ok(())
}

async fn user_test(client: &Client) -> Result<()> {
let user_name_a = "test_user_A";
let user_name_b = "test_user_B";
let password = "test_password";
let new_password = "new_password";
let old_password = "test_password";
println!("========== Start user test ==========");
//create user
client.create_user(user_name_a, password).await?;
client.create_user(user_name_b, password).await?;
let res = client.list_users().await?;
println!("After create users: {:?}", res);
//describe user
let res = client.describe_user(user_name_a).await?;
println!("Describe user_a: {:?}", res);
//update password
client
.update_password(user_name_a, old_password, new_password)
.await?;
//describe user
let res = client.describe_user(user_name_a).await?;
println!("After update password: {:?}", res);
//drop user
client.drop_user(user_name_a).await?;
client.drop_user(user_name_b).await?;
let res = client.list_users().await?;
println!("After drop users: {:?}", res);
println!("========== End user test ==========\n");
Ok(())
}

async fn role_test(client: &Client) -> Result<()> {
let user_name_a = "test_user_a";
let role_name_a = "test_role_A";
let role_name_b = "test_role_B";
let password = "test_password";
println!("========== Start role test ==========");
//create role
client.create_role(role_name_a).await?;
client.create_role(role_name_b).await?;
let res = client.list_roles().await?;
println!("After create roles: {:?}", res);
//describe role
let res = client.describe_role(role_name_a).await?;
println!("Describe role_a: {:?}", res);
//grant role
client.create_user(user_name_a, password).await?;
client.grant_role(user_name_a, role_name_a).await?;
let res = client.describe_user(user_name_a).await?;
println!("Grant role to user: {:?}", res);
//revoke role
client.revoke_role(user_name_a, role_name_a).await?;
let res = client.describe_user(user_name_a).await?;
println!("Revoke role from user: {:?}", res);
//drop role
client.drop_role(role_name_a, true).await?;
client.drop_role(role_name_b, true).await?;
let res = client.list_roles().await?;
println!("After drop roles: {:?}", res);
//drop user
client.drop_user(user_name_a).await?;
println!("========== End role test ==========\n");
Ok(())
}

async fn privilege_test(client: &Client) -> Result<()> {
let privilege_group_name = "test_privilege_group";
let privilege_name = "ShowCollections";
let role_name = "test_role";
let user_name = "test_user";
let password = "test_password";
println!("========== Start privilege test ==========");
//create privilege group
if client
.list_privilege_groups()
.await?
.contains_key(&privilege_group_name.to_string())
{
client.drop_privilege_group(privilege_group_name).await?;
}
client.create_privilege_group(privilege_group_name).await?;
let res = client.list_privilege_groups().await?;
println!("After create privilege group: {:#?}", res);
//create role
if client.list_roles().await?.contains(&role_name.to_string()) {
client.drop_role(role_name, true).await?;
}
client.create_role(role_name).await?;
//create user
if client.list_users().await?.contains(&user_name.to_string()) {
client.drop_user(user_name).await?;
}
client.create_user(user_name, password).await?;
//grant privilege
client
.grant_privilege(role_name, privilege_name, "Global", "*", None)
.await?;
let res = client.describe_role(role_name).await?;
println!("After grant privilege: {:#?}", res);
//add privilege to group
client
.add_privilege_to_group(privilege_group_name, vec![privilege_name.to_string()])
.await?;
let res = client.list_privilege_groups().await?;
println!("After add privilege to group: {:#?}", res);
//revoke privilege from group
client
.revoke_privilege_from_group(privilege_group_name, vec![privilege_name.to_string()])
.await?;
let res = client.list_privilege_groups().await?;
println!("After revoke privilege from group: {:#?}", res);
//revoke privilege
client
.revoke_privilege(role_name, "Global", "ShowCollections", "*", None)
.await?;
let res = client.describe_role(role_name).await?;
println!("After revoke privilege: {:#?}", res);
//drop privilege group
client.drop_privilege_group(privilege_group_name).await?;
let res = client.list_privilege_groups().await?;
println!("After drop privilege group: {:#?}", res);
//drop role
client.drop_role(role_name, true).await?;
client.drop_user(user_name).await?;
println!("========== End privilege test ==========\n");
Ok(())
}
68 changes: 68 additions & 0 deletions examples/database.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
use milvus::error::Result;
use milvus::schema::{CollectionSchemaBuilder, FieldSchema};
use milvus::{client::Client, database::CreateDbOptions};

const TEST_NAME_A: &str = "test_database_A";
const TEST_NAME_B: &str = "test_database_B";

#[tokio::main]
async fn main() -> Result<()> {
let mut client = Client::new("http://localhost:19530").await?;

//create database with properties
let db_properties = CreateDbOptions::new().replica_number(1).max_collections(3);
client
.create_database(TEST_NAME_A, Some(db_properties))
.await?;
let db_properties = CreateDbOptions::new().replica_number(1).max_collections(3);
client
.create_database(TEST_NAME_B, Some(db_properties))
.await?;

//list database
let res = client.list_databases().await?;
println!("After create databases:{:?}", res);

//describe database
let res = client.describe_database(TEST_NAME_A).await?;
println!("Describe database_A : \n{:#?}", res);

//alter database properties
let options = CreateDbOptions::new().replica_number(0).max_collections(2);
client
.alter_database_properties(TEST_NAME_A, options)
.await?;
let res = client.describe_database(TEST_NAME_A).await?;
println!("After alter database_A properties:\n{:#?}\n", res);

//using database
let collection_name_a = "collection_A";
let collection_name_b = "collection_B";
let schema_a = CollectionSchemaBuilder::new(collection_name_a, "For database test")
.add_field(FieldSchema::new_primary_int64("id", "", true))
.add_field(FieldSchema::new_float_vector("vector_A", "", 128))
.build()?;
let schema_b = CollectionSchemaBuilder::new(collection_name_b, "For database test")
.add_field(FieldSchema::new_primary_int64("id", "", true))
.add_field(FieldSchema::new_float_vector("vector_B", "", 128))
.build()?;
//use db_A
client.using_database(TEST_NAME_A).await?;
client.create_collection(schema_a, None).await?;
let res = client.list_collections().await?;
println!("Database A collections: {:?} ", res);
client.drop_collection(collection_name_a).await?;
//use db_B
client.using_database(TEST_NAME_B).await?;
client.create_collection(schema_b, None).await?;
let res = client.list_collections().await?;
println!("Database B collections: {:?}", res);
//drop database
client.drop_collection(collection_name_b).await?;

client.drop_database(TEST_NAME_A).await?;
client.drop_database(TEST_NAME_B).await?;
let res = client.list_databases().await?;
println!("After drop database A and B there are databases: {:?}", res);
Ok(())
}
135 changes: 135 additions & 0 deletions examples/index_example.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
use milvus::{
client::Client,
data::FieldColumn,
index::{IndexParams, IndexType, MetricType},
options::LoadOptions,
query::QueryOptions,
schema::{CollectionSchemaBuilder, FieldSchema},
};
use rand::Rng;
use std::collections::HashMap;

const DIM: i64 = 8;
const COLLECTION_NAME: &str = "hello_milvus";

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = Client::new("http://localhost:19530").await?;

if client.has_collection(COLLECTION_NAME).await? {
println!("Dropping existing collection: {}", COLLECTION_NAME);
client.drop_collection(COLLECTION_NAME).await?;
}

let mut schema = CollectionSchemaBuilder::new(COLLECTION_NAME, "Hello Milvus collection");
schema
.add_field(FieldSchema::new_primary_int64("id", "", true)) // is_primary = true
.add_field(FieldSchema::new_float_vector("embeddings", "", DIM))
.add_field(FieldSchema::new_varchar("title", "", 64))
.enable_dynamic_field();

let schema = schema.build()?;

println!("Creating collection");
client.create_collection(schema.clone(), None).await?;

println!("Start inserting entities");
let mut rng = rand::thread_rng();

let mut embeddings_data = Vec::new();
let mut title_data = Vec::new();

for i in 1..=6 {
embeddings_data.extend((0..DIM).map(|_| rng.gen::<f32>()));
title_data.push(format!("t{}", i));
}

let embeddings_col = FieldColumn::new(schema.get_field("embeddings").unwrap(), embeddings_data);
let title_col = FieldColumn::new(schema.get_field("title").unwrap(), title_data);

let insert_result = client
.insert(COLLECTION_NAME, vec![embeddings_col, title_col], None)
.await?;
println!("Inserting entities done");
println!("Insert result: {:?}", insert_result);

client.flush(COLLECTION_NAME).await?;

println!("Start create index for embeddings");
let index_params = IndexParams::new(
"embeddings_index".to_string(),
IndexType::IvfFlat,
MetricType::L2,
HashMap::from([("nlist".to_string(), "32".to_string())]),
);
client
.create_index(COLLECTION_NAME, "embeddings", index_params)
.await?;

println!("Start create index for title");
let title_index_params = IndexParams::new(
"my_trie".to_string(),
IndexType::Trie,
MetricType::L2,
HashMap::new(),
);
client
.create_index(COLLECTION_NAME, "title", title_index_params)
.await?;

let index_names = client.list_indexes(COLLECTION_NAME, None).await?;
println!("Index names for {}: {:?}", COLLECTION_NAME, index_names);

for index_name in &index_names {
let index_info = client.describe_index(COLLECTION_NAME, index_name).await?;
println!("Index info for index {}: {:?}", index_name, index_info);
}

println!("Start load collection");
client
.load_collection(COLLECTION_NAME, Some(LoadOptions::default()))
.await?;

println!("Start query by specifying primary keys");
let query_options = QueryOptions::default();
let query_results = client
.query(COLLECTION_NAME, "id == 2", &query_options)
.await?;
if let Some(result) = query_results.first() {
println!("Query result: {:?}", result);
}

println!("Start query by specifying filtering expression");
let query_results = client
.query(COLLECTION_NAME, "title == 't2'", &query_options)
.await?;
for ret in query_results {
println!("Query result: {:?}", ret);
}

let field_index_names = client
.list_indexes(COLLECTION_NAME, Some("embeddings"))
.await?;
println!(
"Index names for {}'s field embeddings: {:?}",
COLLECTION_NAME, field_index_names
);

println!("Try to drop index");
client.release_collection(COLLECTION_NAME).await?;

match client.drop_index(COLLECTION_NAME, "my_trie").await {
Ok(_) => println!("Successfully dropped index for title field"),
Err(e) => println!("Caught error when dropping index: {}", e),
}

match client.drop_index(COLLECTION_NAME, "my_trie").await {
Ok(_) => println!("Successfully dropped index for title field"),
Err(e) => println!("Caught error when dropping index: {}", e),
}

client.drop_collection(COLLECTION_NAME).await?;

println!("Example completed successfully!");
Ok(())
}
Loading
Loading