#vector-database #database-client #vector #weaviate

weaviate-community

用Rust编写的Rust社区客户端,用于处理Weaviate矢量数据库事务

3个版本

0.2.2 2024年2月17日
0.2.1 2024年2月10日
0.2.0 2023年11月25日
0.1.0 2023年10月4日

#782数据库接口

Download history 1/week @ 2024-03-12 17/week @ 2024-04-02 126/week @ 2024-04-23

每月160 次下载

MIT 许可证

345KB
5.5K SLoC

Weaviate Community

Crates.io CircleCI License

用Rust编写的Rust社区客户端,用于处理Weaviate矢量数据库事务。

关于Weaviate的更多信息可以在官方 Weaviate 网页上找到。

安装

在您的项目目录中运行以下命令

cargo add weaviate-community

或者将以下内容添加到您的 Cargo.toml 文件中

weaviate-community = "0.2.2"

文档

库参考文档可以在 这里 找到

使用方法

以下是一些如何与Weaviate社区Rust客户端交互的示例。

创建一个新的WeaviateClient

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("https://127.0.0.1:8080")
        .build()?;
    
    // With Auth key
    let client = WeaviateClient::builder("https://127.0.0.1:8080")
        .with_auth_secret("your-key")
        .build()?;

    // With multiple other API key (eg, OpenAI, JinaAI, ..)
    let client = WeaviateClient::builder("https://127.0.0.1:8080")
        .with_auth_secret("your-key")
        .with_api_key("X-OpenAI-Api-Key", "abcdefg")
        .with_api_key("X-Jinaai-Api-Key", "hijklmn")
        .build()?;

    Ok(())
}

模式端点

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(())
}

对象端点

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(())
}

备份端点

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(())
}

批量端点

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(())
}

元数据端点

async fn meta_endpoint(client: WeaviateClient) -> Result<(), Box<dyn Error>> {
    // Get database metadata
    let res = client.meta.get_meta().await?;

    Ok(())
}

节点端点

async fn nodes_endpoint(client: WeaviateClient) -> Result<(), Box<dyn Error>> {
    // Get the nodes status'
    let res = client.nodes.get_nodes_status().await?;

    Ok(())
}

OIDC端点

async fn oidc_endpoint(client: WeaviateClient) -> Result<(), Box<dyn Error>> {
    // Get the OIDC config
    let res = client.oidc.get_open_id_configuration().await?;

    Ok(())
}

查询

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(())
}

健康端点

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(())
}

分类端点

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(())
}

模块(text2vec-contextionary)端点

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(())
}

路线图

  • SI测试更新
  • 改进GraphQL查询系统(以及批量删除匹配配置)
  • 一个命令创建完整的模式
  • 对反序列化对象中尽可能减少serde_json的一般改进
  • 嵌入式功能
  • gRPC(在官方客户端进行beta测试后)

贡献

欢迎在 GitHub 上提交任何错误报告和功能请求

许可证

本项目采用 MIT开源许可证

依赖项

~6–21MB
~291K SLoC