# Weaviate Community [![Crates.io][crates-badge]][crates-url] [![CircleCI][circleci-badge]][circleci-url] [![License][license-badge]][github-url] [crates-badge]: https://img.shields.io/crates/v/weaviate-community.svg [license-badge]: https://img.shields.io/badge/license-MIT-green.svg [circleci-badge]: https://circleci.com/gh/Sam-Pewton/weaviate-community.rust.svg?style=shield [crates-url]: https://crates.io/crates/weaviate-community [circleci-url]: https://app.circleci.com/pipelines/github/Sam-Pewton/weaviate-community.rust [github-url]: https://github.com/Sam-Pewton/weaviate-community.rust [mit-url]: https://opensource.org/license/mit/ [rsdocs-url]: https://docs.rs/weaviate-community/0.2.2/weaviate_community/ [weaviate-url]: https://weaviate.io/developers/weaviate Community client for handling Weaviate vector database transactions written in Rust, for Rust. More information on Weaviate can be found on the official [Weaviate][weaviate-url] webpage. # Installation Run the following in your project directory ```bash cargo add weaviate-community ``` or add the following to your `Cargo.toml` file ```text weaviate-community = "0.2.2" ``` # Documentation The library reference documentation can be found [here][rsdocs-url] # Usage Below are some examples on how to interact with the Weaviate community Rust client. ## Creating a new WeaviateClient ```rust use std::error::Error; use weaviate_community::WeaviateClient; use weaviate_community::collections::auth::AuthApiKey; #[tokio::main] async fn main() -> Result<(), Box> { // With anonymous access let client = WeaviateClient::builder("http://localhost:8080") .build()?; // With Auth key let client = WeaviateClient::builder("http://localhost:8080") .with_auth_secret("your-key") .build()?; // With multiple other API key (eg, OpenAI, JinaAI, ..) let client = WeaviateClient::builder("http://localhost:8080") .with_auth_secret("your-key") .with_api_key("X-OpenAI-Api-Key", "abcdefg") .with_api_key("X-Jinaai-Api-Key", "hijklmn") .build()?; Ok(()) } ``` ## Schema endpoints ```rust use weaviate_community::collections::schema::{ Class, Property, ShardStatus, Tenants, Tenant, ActivityStatus }; async fn schema_endpoints(client: WeaviateClient) -> Result<(), Box> { // Get full schema let res = client.schema.get().await?; // Get the schema for a single class let res = client.schema.get_class("Article").await?; // Create a new class in the schema let my_class = Class::builder("Article").with_description("News article").build(); let res = client.schema.create_class(&my_class).await?; // Update a class in the schema let my_class = Class::builder("Article").with_description("Updated information").build(); let res = client.schema.update(&my_class).await?; // Add a property to a class let property = Property::builder("title", vec!["text"]).build(); let res = client.schema.add_property("Article", &property).await?; // Get the shards for a class let res = client.schema.get_shards("Article").await?; // Update a class shard let res = client.schema.update_class_shard("Article", "abcdefg", ShardStatus::READONLY).await?; // List tenants for a class let res = client.schema.list_tenants("Article").await?; // Add tenants to a class let tenants = Tenants::new(vec![Tenant::builder("TENANT_B").build()]); let res = client.schema.add_tenants("Article", &tenants).await?; // Update tenants let tenants = Tenants::new( vec![ Tenant::builder("TENANT_B").with_activity_status(ActivityStatus::COLD).build() ] ); let res = client.schema.update_tenants("Article", &tenants).await?; // Remove tenants from a class let tenants = vec!["TENANT_B"]; let res = client.schema.add_tenants("Article", &tenants).await?; // Delete a class from the schema let res = client.schema.delete("Article").await?; Ok(()) } ``` ## Objects endpoints ```rust use uuid::Uuid; use weaviate_community::collections::objects::{Object, ObjectListParameters}; async fn objects_endpoints(client: WeaviateClient) -> Result<(), Box> { // List every single object let res = client.objects.list(ObjectListParameters::new()).await?; // List all objects for a single class let params = ObjectListParameters::builder().with_class_name("Article").build(); let res = client.objects.list(params).await?; // Create a new object let my_object = Object::builder("Article", serde_json::json!({})).build(); let res = client.objects.create(&my_object, None).await?; // Get an object based on its UUID let uuid = Uuid::new_v4(); let res = client.objects.get("Article", uuid, None, None, None).await?; // Check if a data object exists let uuid = Uuid::new_v4(); let res = client.objects.exists("Article", uuid, None, None).await?; // Update a data object let uuid = Uuid::parse_str("ee22d1b8-3b95-4e94-96d5-9a2b60fbd303")?; let properties = serde_json::json!({ "title": "new title", }); let res = client.objects.update(&properties, "Article", &uuid, None).await?; // Replace a data object let uuid = Uuid::parse_str("ee22d1b8-3b95-4e94-96d5-9a2b60fbd303")?; let properties = serde_json::json!({ "properties": { "author": "Jodi Kantor", } }); let res = client.objects.replace(&properties, "Publication", &uuid, None).await?; // Delete a data object let uuid = Uuid::parse_str("ee22d1b8-3b95-4e94-96d5-9a2b60fbd303")?; let res = client.objects.delete("Article", &uuid, None, None).await?; // Validate a data object let properties = serde_json::json!({ "name": "New York Times" }); let uuid = Uuid::parse_str("12345678-1234-1234-1234-123456789012")?; let res = client.objects.validate("Publication", &properties, &uuid).await?; // Add a cross-reference let uuid1 = Uuid::parse_str("12345678-1234-1234-1234-123456789012")?; let uuid2 = Uuid::parse_str("20ffc68d-986b-5e71-a680-228dba18d7ef")?; let reference = Reference::new( "JeopardyQuestion", &uuid1, "hasCategory", "JeopardyCategory", &uuid2, ); let res = client.objects.reference_add(reference).await?; // Update a cross-reference let uuid1 = Uuid::parse_str("12345678-1234-1234-1234-123456789012")?; let uuid2 = Uuid::parse_str("20ffc68d-986b-5e71-a680-228dba18d7ef")?; let res = client.objects.reference_update( "JeopardyQuestion", &uuid1, "hasCategory", vec!["JeopardyCategory"], vec![&uuid2], None, None ).await?; // Delete a cross-reference let uuid1 = Uuid::parse_str("12345678-1234-1234-1234-123456789012")?; let uuid2 = Uuid::parse_str("20ffc68d-986b-5e71-a680-228dba18d7ef")?; let reference = Reference::new( "JeopardyQuestion", &uuid1, "hasCategory", "JeopardyCategory", &uuid2, ); let res = client.objects.reference_delete(reference).await?; Ok(()) } ``` ## Backups endpoints ```rust use weaviate_community::collections::backups::{ BackupCreateRequest, BackupRestoreRequest, BackupBackends }; async fn backups_endpoints(client: WeaviateClient) -> Result<(), Box> { // Create a new backup - with wait for completion let req = BackupCreateRequest::builder("my-backup").build(); let res = client.backups.create(BackupBackends::FILESYSTEM, req, true).await?; // Create a new backup - without wait for completion let req = BackupCreateRequest::builder("my-backup").build(); let res = client.backups.create(BackupBackends::FILESYSTEM, req, false).await?; // Get the status of a backup create let res = client.backups.get_backup_status( BackupBackends::FILESYSTEM, "my-backup", false ).await?; // Restore a backup - with wait for completion let req = BackupRestoreRequest::builder().build(); let res = client.backups.restore(BackupBackends::FILESYSTEM, "my-backup", req, true).await?; // Restore a backup - without wait for completion let req = BackupRestoreRequest::builder().build(); let res = client.backups.restore(BackupBackends::FILESYSTEM, "my-backup", req, false).await?; // Get the status of a backup restore let res = client.backups.get_backup_status( BackupBackends::FILESYSTEM, "my-backup", true ).await?; Ok(()) } ``` ## Batch endpoints ```rust use uuid::Uuid; use weaviate_community::collections::objects::{ Object, MultiObject, Reference, References, ConsistencyLevel, }; use weaviate_community::collections::batch::{BatchDeleteRequest, MatchConfig}; async fn batch_endpoints(client: WeaviateClient) -> Result<(), Box> { // Batch add objects let author_uuid = Uuid::parse_str("36ddd591-2dee-4e7e-a3cc-eb86d30a4303").unwrap(); let article_a_uuid = Uuid::parse_str("6bb06a43-e7f0-393e-9ecf-3c0f4e129064").unwrap(); let article_b_uuid = Uuid::parse_str("b72912b9-e5d7-304e-a654-66dc63c55b32").unwrap(); let article_a = Object::builder("Article", serde_json::json!({})) .with_id(article_a_uuid.clone()) .build(); let article_b = Object::builder("Article", serde_json::json!({})) .with_id(article_b_uuid.clone()) .build(); let author = Object::builder("Author", serde_json::json!({})) .with_id(author_uuid.clone()) .build(); let res = client.batch.objects_batch_add( MultiObjects::new( vec![article_a, article_b, author]), Some(ConsistencyLevel::ALL), None ).await?; // Batch delete objects let req = BatchDeleteRequest::builder( MatchConfig::new( "Article", serde_json::json!({ "operator": "Like", "path": ["id"], "valueText": "*4*", }) ) ).build(); let res = client.batch.objects_batch_delete( req, Some(ConsistencyLevel::ALL), None ).await?; // Batch add references let references = References::new(vec![ Reference::new( "Author", &author_uuid, "wroteArticles", "Article", &article_a_uuid, ), Reference::new( "Author", &author_uuid, "wroteArticles", "Article", &article_b_uuid, ), ]); let res = client.batch.references_batch_add( references, Some(ConsistencyLevel::ALL), None ).await?; Ok(()) } ``` ## Meta endpoint ```rust async fn meta_endpoint(client: WeaviateClient) -> Result<(), Box> { // Get database metadata let res = client.meta.get_meta().await?; Ok(()) } ``` ## Nodes endpoint ```rust async fn nodes_endpoint(client: WeaviateClient) -> Result<(), Box> { // Get the nodes status' let res = client.nodes.get_nodes_status().await?; Ok(()) } ``` ## OIDC endpoint ```rust async fn oidc_endpoint(client: WeaviateClient) -> Result<(), Box> { // Get the OIDC config let res = client.oidc.get_open_id_configuration().await?; Ok(()) } ``` ## Querying ```rust use weaviate_community::collections::query::{ GetQuery, AggregateQuery, ExploreQuery, RawQuery }; async fn querying(client: WeaviateClient) -> Result<(), Box> { // Get let query = GetQuery::builder( "JeopardyQuestion", vec![ "question", "answer", "points", "hasCategory { ... on JeopardyCategory { title }}" ]) .with_limit(1) .with_additional(vec!["id"]) .build(); let res = client.query.get(query).await?; // Aggregate let query = AggregateQuery::builder("Article") .with_meta_count() .with_fields(vec!["wordCount {count maximum mean median minimum mode sum type}"]) .build(); let res = client.query.aggregate(query).await?; // Explore let query = ExploreQuery::builder() .with_limit(1) .with_near_vector("{vector: [-0.36840257,0.13973749,-0.28994447]}") .with_fields(vec!["beacon", "className", "certainty"]) .build(); let res = client.query.explore(query).await?; // Raw let query = RawQuery::new("{ Get { JeopardyQuestion { question answer points } } }"); let res = client.query.raw(query).await?; Ok(()) } ``` ## Health endpoints ```rust async fn health_endpoints(client: WeaviateClient) -> Result<(), Box> { // Check database is live let res = client.is_live().await?; // Check database is ready let res = client.is_ready().await?; Ok(()) } ``` ## Classification endpoints ```rust use uuid::Uuid; use weaviate_community::collections::classification::{ ClassificationRequest, ClassificationType }; async fn classification_endpoints(client: WeaviateClient) -> Result<(), Box> { // Schedule a new classification let req = ClassificationRequest::builder() .with_type(ClassificationType::KNN) .with_class("Article") .with_based_on_properties(vec!["summary"]) .with_classify_properties(vec!["hasPopularity"]) .with_filters(serde_json::json!({ "trainingSetWhere": { "path": ["wordCount"], "operator": "GreaterThan", "valueInt": 100 } })) .with_settings(serde_json::json!({ "k": 3 })) .build(); let res = client.classification.schedule(req).await?; // Get the status of a classification let uuid = Uuid::parse_str("00037775-1432-35e5-bc59-443baaef7d80")?; let res = client.classification.get(uuid).await?; Ok(()) } ``` ## Module (text2vec-contextionary) endpoints ```rust use weaviate_community::collections::modules::ContextionaryExtend; async fn module_endpoints(client: WeaviateClient) -> Result<(), Box> { // Get a concept let res = client.modules.contextionary_get_concept("magazine").await?; // Extend contextionary let ext = ContextionaryExtension::new( "weaviate", "Open source cloud native real time vector database", 1.0 ); let res = client.modules.contextionary_extend(ext).await?; Ok(()) } ``` # Roadmap - SI test update - Improvements to the GraphQL query system (and batch delete match config) - Create full schema in one command - General improvements to try and remove as much serde_json in the deserialized objects.. - Embedded functionality - gRPC (after beta testing for official clients) # Contributing Any bug reports and feature requests welcome on [GitHub][github-url] # License This project is licensed under the [MIT License][mit-url] open-source license.