---
title: "Rust"
description: "Client, Agnesoft Graph Database."
---

import { Callout, Steps } from "nextra/components";

# 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](https://crates.io/crates/reqwest). 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](/docs/guides/how-to-run-server) to learn how to run the server.

Looking for... [how to run a server?](/docs/guides/how-to-run-server) | [another language?](/api-docs/openapi) | [embedded db guide?](/docs/guides/quickstart)

## Usage

<Steps>

### Install Rust

Please install the Rust toolchain from the [official source](https://www.rust-lang.org/tools/install).

### Create an applicaiton

First we initialize an application called `agdb_client` with cargo:

```
cargo init agdb_client
```

### Add dependencies

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

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

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

```rs
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.

<Callout>
    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`.
</Callout>

```rs
// 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:

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

</Steps>
