Light
Dark
System
v3latest
v3latest
v2
v1

Using the client

Creating a new EdgeDB client can be done in a single line:

Copy
let client = edgedb_tokio::create_client().await?;

Under the hood, this will create a Builder, look for environment variables and/or an edgedb.toml file, and return an Ok(Self) if successful. This Builder can be used on its own instead of create_client() if you need a more customized setup.

Queries with the client

Here are the simplified signatures of the client methods used for querying:

R here means a type that implements QueryResult. (See more on QueryResult and QueryArgs on the edgedb-protocol documentation.)

Copy
fn query -> Result<Vec<R>, Error>
fn query_json -> Result<Json, Error>

fn query_single -> Result<Option<R>, Error>
fn query_single_json -> Result<Option<Json>>

fn query_required_single -> Result<R, Error>
fn query_required_single_json -> Result<Json, Error>

fn execute -> Result<(), Error>

Note the difference between the _single and the _required_single methods:

  • The _required_single methods return empty results as a NoDataError which allows propagating errors normally through an application.

  • The _single methods will simply give you an Ok(None) in this case.

These methods all take a query (a &str) and arguments (something that implements the QueryArgs trait).

The () unit type implements QueryArgs and is used when no arguments are present so &() is a pretty common sight when using the Rust client.

Copy
// Without arguments: just add &() after the query
let query_res: String =
    client.query_required_single("select 'Just a string'", &()).await?;

// With arguments, same output as the previous example
let a = " a ";
let b = "string";
let query_res: String = client
    .query_required_single("select 'Just' ++ <str>$0 ++ <str>$1", &(a, b))
    .await?;

For more, see the section on passing in arguments.

These methods take two generic parameters which can be specified with the turbofish syntax:

Copy
let query_res = client
     .query_required_single::<String, ()>("select 'Just a string'", &())
     .await?;
// or
let query_res = client
     .query_required_single::<String, _>("select 'Just a string'", &())
     .await?;

But declaring the final expected type upfront tends to look neater.

Copy
let query_res: String = client
    .query_required_single("select 'Just a string'", &())
    .await?;

When cardinality is guaranteed to be 1

Using the .query() method works fine for any cardinality, but returns a Vec of results. This query with a cardinality of 1 returns a Result<Vec<String>> which becomes a Vec<String> after the error is handled:

Copy
let query = "select 'Just a string'";
let query_res: Vec<String> = client.query(query, &()).await?;

But if you know that only a single result will be returned, using .query_required_single() or .query_single() will be more ergonomic:

Copy
let query = "select 'Just a string'";
let query_res: String = client
    .query_required_single(query, &()).await?;
let query_res_opt: Option<String> = client
    .query_single(query, &()).await?;
Light
Dark
System

We use ChatGPT with additional context from our documentation to answer your questions. Not all answers will be accurate. Please join our Discord if you need more help.