# 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.1/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.1"
```
# 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<dyn Error>> {
// 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<dyn Error>> {
// 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<dyn Error>> {
// 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<dyn Error>> {
// 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<dyn Error>> {
// 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<dyn Error>> {
// Get database metadata
let res = client.meta.get_meta().await?;
Ok(())
}
```
## Nodes endpoint
```rust
async fn nodes_endpoint(client: WeaviateClient) -> Result<(), Box<dyn Error>> {
// Get the nodes status'
let res = client.nodes.get_nodes_status().await?;
Ok(())
}
```
## OIDC endpoint
```rust
async fn oidc_endpoint(client: WeaviateClient) -> Result<(), Box<dyn Error>> {
// 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<dyn Error>> {
// 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<dyn Error>> {
// 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<dyn Error>> {
// 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<dyn Error>> {
// 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.