Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.satoridb.com/llms.txt

Use this file to discover all available pages before exploring further.

πŸ“š 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


### πŸ”Ή ann

Perform an Aproximate Nearest Neighbors search

```rust
client.ann(serde_json::json!({
    "key": "user:123", //or vector: [f32]
    "top_k" : 5 //return the top 5 neighbors
})).await?;
```

### πŸ”Ή query

Make a query to the db in natural language

```rust
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

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

### πŸ”Ή set_middleware
Make the LLM analyze incoming querys and decide if it must reject them, accept them or modify them.
```rust
client.set_middleware(serde_json::json!({
    "operation": "SET",
    "middleware": "Only accept requests that have the amount field specified, and convert its value to dollars"
})).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.

## Analytics

### πŸ”Ή get_operations

Returns all operations executed on the database.

### πŸ”Ή get_access_frequency

Returns the number of times an object has been queried or accessed.
```rust
client.get_access_frequency(serde_json::json!({
    "key": "user:1",
})).await?;
```

---

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

You can use the `Schema` struct to model your data in an object-oriented way:

```rust
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

```rust
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:

```ts
{
  data: any //the requested data if any
  message: string //status message
  type: string //SUCCESS || ERROR
}
```

AI responses obbey a different patern:

## ask

```ts
{
  response: string //response to the question
}
```

## query

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

## ann

```ts
{
  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.

---