API
Rust

Rust

The rust agdb API client is async only and can be used with any HTTP client that would implement the agdb_api::HttpClient trait. The default implementation uses reqwest (opens in a new tab). The following is the quickstart guide for the agdb client in Rust (connecting to the server). It assumes an agdb_server is running locally. Please refer to the server guide to learn how to run the server.

Looking for... how to run a server? | another language? | embedded db guide?

Usage

Install Rust

Please install the Rust toolchain from the official source (opens in a new tab).

Create an applicaiton

First we initialize an application called agdb_client with cargo:

cargo init agdb_client

Add dependencies

cargo add agdb --features serde,openapi
cargo add agdb_api --features reqwest
cargo add tokio --features  full
cargo add anyhow

Create the client

The client should point to a running agdb_server:

use agdb_api::AgdbApi;
use agdb_api::ReqwestClient;
 
#[tokio:main]
async fn main() -> anyhow::Result<()> {
    let mut client = AgdbApi::new(ReqwestClient::new(), "localhost:3000");
 
    Ok(())
}

Create a database user

First we need to login as default admin user and create our database user and then login as them:

client.user_login("admin", "admin").await?; // The authentication login is stored in
                                            // the client for subsequent API calls.
                                            // Default admin credentials are "admin/admin".
client.admin_user_add("my_user", "password123").await?;
client.user_login("my_user", "password123").await?; // Login as our newly created user.

Create a database

use agdb_api::DbType;
 
client.db_add("my_user", "my_db", DbType::Mapped).await?; // Memory mapped database called "my_db"
                                                          // will be created under our "my_user".

Run our first queries

To run queries against the database we call exec. In this case we will insert node "users" and 3 user nodes and connect them together.

💡

Note that we can feed the result of a previous query directly to the next one referencing it with an index into the (previous) results starting with semicolon followed by the index, e.g. :0, :1.

// We derive from agdb::UserValue
// so we can use the type in the db.
#[derive(Debug, UserValue)]
struct User {
    db_id: Option<DbId>, // The db_id member is optional but
                         // it allows querying your user type
                         // from the database.
    username: String
    age: u64,
}
 
let users = vec![User { db_id: None, username: "Alice".to_string(), age: 40 },
                 User { db_id: None, username: "Bob".to_string(), age: 30 },
                 User { db_id: None, username: "John".to_string(), age: 20 }];
 
// We can pass users directly as
// query paramter thanks to the
// implementation of the agdb::DbUserValue
// trait via #[derive(UserValue)].
let queries: Vec<QueryType> = vec![QueryBuilder::insert().nodes().aliases("users").query().into(),
                                   QueryBuilder::insert().nodes().values(&users).query().into(),
                                   QueryBuilder::insert().edges().from("users").to(":1").query().into(),
                            ];
 
client.exec("my_user", "my_db", &queries).await?;

Run more queries

Run another query searching & selecting the users and converting them back to the native local object and printing the result:

let queries = vec![QueryBuilder::select()
                    .values(User::db_keys()) // Select only relevant properties for the User struct.
                    .ids(
                        QueryBuilder::search()
                            .from("users") // Start the search from the "users" node.
                            .where_()
                            .key("age") // Examine "age" property.
                            .value(LessThan(40.into())) // Include it in the search result if the value
                                                        // is less than 40.
                            .query(),
                    )
                    .query()];
 
// Runs the query against the db, grabs the first result and converts it to the collection of users.
let users: Vec<User> = client.exec("my_user", "my_db", &queries).await?[0].try_into()?;
 
println!("{:?}", users);

Run the program

cargo run

Full program

https://github.com/agnesoft/agdb/tree/main/examples/server_client_rust (opens in a new tab)