πŸ“š Satori Rust SDK

This library allows you to easily and efficiently interact with the Satori database via WebSockets, supporting CRUD operations, real-time notifications, advanced queries, and graph-like relations.

✨ Main Features

  • Ultra-fast CRUD operations ⚑
  • Advanced queries using field_array πŸ”
  • Real-time notifications πŸ“’
  • Graph-like relations (vertices and references) πŸ•ΈοΈ
  • Data encryption and decryption πŸ”

πŸš€ Installation

Add the following to your Cargo.toml:
[dependencies]
satori-client = "0.1.4"
tokio = { version = "1.36", features = ["full"] }

🏁 Basic Usage

use satori_client::Satori;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let client = Satori::connect(
        "username".to_string(),
        "password".to_string(),
        "ws://localhost:8000".to_string()
    ).await?;

    // Example: set data
    client.set(serde_json::json!({
        "key": "user:123",
        "data": { "name": "John", "email": "john@example.com" },
        "type": "user"
    })).await?;

    Ok(())
}

πŸ—ƒοΈ CRUD Operations

Create Data

client.set(serde_json::json!({
    "key": "user:123",
    "data": { "name": "John", "email": "john@example.com" },
    "type": "user"
})).await?;

Read Data

let user = client.get(serde_json::json!({ "key": "user:123" })).await?;

Modify a Field

client.put(serde_json::json!({
    "key": "user:123",
    "replace_field": "name",
    "replace_value": "Peter"
})).await?;

Delete Data

client.delete(serde_json::json!({ "key": "user:123" })).await?;

🧩 Advanced Queries with field_array πŸ”

You can perform operations on multiple objects that meet certain conditions using the field_array field:
let results = client.get(serde_json::json!({
    "field_array": [
        { "field": "email", "value": "john@example.com" }
    ]
})).await?;
  • field_array is an array of conditions { "field": ..., "value": ... }.
  • You can combine it with "one": true to get only the first matching result.

πŸ”” Real-time Notifications

Receive automatic updates when an object changes:
client.set_notify("user:123", |data| {
    println!("User updated! {:?}", data);
}).await?;

πŸ•ΈοΈ Relations and Graphs

You can create relationships between objects (vertices):
client.set_vertex(serde_json::json!({
    "key": "user:123",
    "vertex": "friend:456",
    "relation": "friend",
    "encryption_key": "secret"
})).await?;
And traverse the graph with DFS:
client.dfs(serde_json::json!({
    "node": "user:123",
    "encryption_key": "secret"
})).await?;
Get all neighbors of an object:
client.get_vertex(serde_json::json!({
    "key": "user:123",
    "encryption_key": "secret",
    "relation": "friends"
})).await?;
Remove a specific neighbor:
client.delete_vertex(serde_json::json!({
    "key": "user:123",
    "vertex": "user:512",
    "encryption_key": "secret"
})).await?;

πŸ” Encryption and Security

Easily encrypt and decrypt data:
client.encrypt(serde_json::json!({
    "key": "user:123",
    "encryption_key": "secret"
})).await?;

client.decrypt(serde_json::json!({
    "key": "user:123",
    "encryption_key": "secret"
})).await?;

πŸ“¦ Array Manipulation Methods

Below are the available methods to manipulate arrays in the Satori database using the Rust client:

πŸ”Ή push

Adds a value to an existing array in an object.
client.push(serde_json::json!({
    "key": "user:123",
    "array": "friends",
    "value": "user:456"
})).await?;

πŸ”Ή pop

Removes the last element from an array in an object.
client.pop(serde_json::json!({
    "key": "user:123",
    "array": "friends"
})).await?;

πŸ”Ή splice

Modifies an array in an object (for example, to cut or replace elements).
client.splice(serde_json::json!({
    "key": "user:123",
    "array": "friends"
})).await?;

πŸ”Ή remove

Removes a specific value from an array in an object.
client.remove(serde_json::json!({
    "key": "user:123",
    "array": "friends",
    "value": "user:456"
})).await?;
## πŸ€– AI Methods

### πŸ”Ή train
Train an embedding model with your data. The model is accessible on `localhost:5000/model` The model will be at the root of your db in the `satori_semantic_model` folder.
```rust
client.train(serde_json::json!({
})).await?;

πŸ”Ή ann

Perform an Aproximate Nearest Neighbors search
client.ann(serde_json::json!({
    "key": "user:123",
    "top_k" : 5 //return the top 5 neighbors
})).await?;

πŸ”Ή query

Make a query to the db in natural language
client.query(serde_json::json!({
    "query": "Insert the vertex user:2 to user:123",
    "backend": "openai:gpt-4o-mini"
})).await?;

πŸ”Ή ask

Ask questions about your data
client.ask(serde_json::json!({
    "question": "How many users over 25 do we have",
    "backend": "openai:gpt-4o-mini"
})).await?;

Notes on AI

In the functions where backend must be specified this parameter must passed with the following format: openai:model-name or ollama:model-name. If you’re using OpenAI as your backend you must specify the OPENAI_API_KEY env variable. If backend isn’t specified openai:gpt-4o-mini will be used as default. The trained embedding model will be at the root of your db in a folder called satori_semantic_model. You can train your embedding model manually whenever you want to but Satori will automatically fine-tune your model with any new updates and use this updated model for all emebedding operations.

πŸ¦€ Schema Struct (Data Model) β€” Rust

You can use the Schema struct to model your data in an object-oriented way:
use satori_client::{Satori, Schema};

let satori = Satori::connect("username", "password", "ws://localhost:1234").await.unwrap();

let mut user = Schema::new(&satori, "user", Some("my_key".into()), Some(json!({ "name": "Anna" })));

user.set().await.unwrap();

It includes useful methods such as:
  • set, delete, encrypt, decrypt, set_vertex, get_vertex, delete_vertex, dfs
  • Array methods: push, pop, splice, remove

πŸ“ Complete Example

use satori_client::Satori;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let client = Satori::connect(
        "username".to_string(),
        "password".to_string(),
        "ws://localhost:8000".to_string()
    ).await?;

    client.set(serde_json::json!({
        "key": "user:1",
        "data": { "name": "Carlos", "age": 30 },
        "type": "user"
    })).await?;

    client.set_notify("user:1", |data| {
        println!("Real-time update: {:?}", data);
    }).await?;

    Ok(())
}

🧠 Key Concepts

  • key: Unique identifier of the object.
  • type: Object type (e.g., β€˜user’).
  • field_array: Advanced filters for bulk operations.
  • notifications: Subscription to real-time changes.
  • vertices: Graph-like relationships between objects.

Responses

All responses obbey the following pattern:
{
  data: any //the requested data if any
  message: string //status message
  type: string //SUCCESS || ERROR
}
AI responses obbey a different patern:

ask

{
  response: string //response to the question
}

query

{
  result: string //response from the operation made in the db
  status: string //status
}

ann

{
  results: array //response from the operation made in the db
}

πŸ’¬ Questions or Suggestions?

Feel free to open an issue or contribute! With ❀️ from the Satori team.