
Embedding in Rust
SurrealDB is designed to be run in many different ways, and environments. Due to the separation of the storage and API layers, SurrealDB can be run in embedded mode, from within a number of different language environments. In Rust, SurrealDB can be run as an in-memory database, it can persist data using a file-based storage engine, or on a distributed cluster.
Install the SDK
First, create a new project using cargo new and add the SurrealDB crate to your dependencies, enabling the key-value store you need:
cargo add surrealdb --features kv-mem
cargo add surrealdb --features kv-rocksdb
cargo add surrealdb --features kv-tikv
You will need to add the following additional dependencies:
cargo add serde --features derive
cargo add tokio --features macros,rt-multi-thread
Connect to SurrealDB
Open src/main.rs and replace everything in there with the following code to try out some basic operations using the SurrealDB SDK with an embedded database. Look at integrations to connect to a database.
use serde::{Deserialize, Serialize};
use surrealdb::RecordId;
use surrealdb::Surreal;
use surrealdb::engine::local::Mem;
#[derive(Debug, Serialize)]
struct Name<'a> {
first: &'a str,
last: &'a str,
}
#[derive(Debug, Serialize)]
struct Person<'a> {
title: &'a str,
name: Name<'a>,
marketing: bool,
}
#[derive(Debug, Serialize)]
struct Responsibility {
marketing: bool,
}
#[derive(Debug, Deserialize)]
struct Record {
#[allow(dead_code)]
id: RecordId,
}
#[tokio::main]
async fn main() -> surrealdb::Result<()> {
let db = Surreal::new::<Mem>(()).await?;
db.use_ns("test").use_db("test").await?;
let created: Option<Record> = db
.create("person")
.content(Person {
title: "Founder & CEO",
name: Name {
first: "Tobie",
last: "Morgan Hitchcock",
},
marketing: true,
})
.await?;
dbg!(created);
let updated: Option<Record> = db
.update(("person", "jaime"))
.merge(Responsibility { marketing: true })
.await?;
dbg!(updated);
let people: Vec<Record> = db.select("person").await?;
dbg!(people);
let groups = db
.query("SELECT marketing, count() FROM type::table($table) GROUP BY marketing")
.bind(("table", "person"))
.await?;
dbg!(groups);
Ok(())
}
Run your program from the command line with:
cargo run
SDK methods
The Rust SDK comes with a number of built-in functions.
.init()
The DB static singleton ensures that a single database instance is available across very large or complicated applications. With the singleton, only one connection to the database is instantiated, and the database connection does not have to be shared across components or controllers.
Method Syntax
Surreal::init()
Example usage
static DB: LazyLock<Surreal<Client>> = LazyLock::new(Surreal::init);
#[tokio::main]
async fn main() -> surrealdb::Result<()> {
DB.connect::<Wss>("cloud.surrealdb.com").await?;
DB.use_ns("test").use_db("test").await?;
let tobie: Option<Record> = DB
.update(("person", "tobie"))
.content(Person { name: "Tobie" })
.await?;
Ok(())
}
.connect()
Connects to a local or remote database endpoint.
Method Syntax
db.connect(endpoint)
Arguments
| Argument | Description |
|---|
endpoint required | The database endpoint to connect to. |
Example usage
DB.connect::<Ws>("127.0.0.1:8000").await?;
DB.connect::<Wss>("cloud.surrealdb.com").await?;
.new()
Connects to a local or remote database endpoint.
Method Syntax
Surreal::new::<T>(endpoint)
Arguments
| Arguments | Description |
|---|
endpoint required | The database endpoint to connect to. |
Example usage
let db = Surreal::new::<Ws>("127.0.0.1:8000").await?;
.use_ns() and .use_db()
Switch to a specific namespace and database.
Method Syntax
db.use_ns(ns).use_db(db)
Arguments
| Arguments | Description |
|---|
ns required | Switches to a specific namespace. |
db required | Switches to a specific database. |
Example usage
db.use_ns("test").use_db("test").await?;
.signup()
Signs up using a specific record access method.
Method Syntax
db.signup(credentials)
Arguments
| Arguments | Description |
|---|
credentials required | Variables used in a signup query. |
Example usage
use serde::Serialize;
use surrealdb::opt::auth::Scope;
#[derive(Serialize)]
struct Credentials<'a> {
email: &'a str,
pass: &'a str,
}
let jwt = db.signup(Scope {
namespace: "test",
database: "test",
access: "user",
params: Credentials {
email: "info@surrealdb.com",
pass: "123456",
},
}).await?;
let token = jwt.as_insecure_token();
.signin()
Signs in using a specific access method or system user.
Method Syntax
db.signin(credentials)
Arguments
| Arguments | Description |
|---|
credentials required | Variables used in a signin query. |
Example usage
use serde::Serialize;
use surrealdb::opt::auth::Scope;
#[derive(Serialize)]
struct Credentials<'a> {
email: &'a str,
pass: &'a str,
}
let jwt = db.signin(Scope {
namespace: "test",
database: "test",
access: "user",
params: Credentials {
email: "info@surrealdb.com",
pass: "123456",
},
}).await?;
let token = jwt.as_insecure_token();
.invalidate()
Invalidates the authentication for the current connection.
Method Syntax
db.invalidate(credentials)
Example usage
db.invalidate().await?;
.authenticate()
Authenticates the current connection with a JWT token.
Method Syntax
db.authenticate(token)
Arguments
| Arguments | Description |
|---|
token required | The JWT authentication token. |
Example usage
db.authenticate(jwt).await?;
.set()
Assigns a value as a parameter for this connection.
Method Syntax
db.set(key, val)
Arguments
| Arguments | Description |
|---|
key required | Specifies the name of the variable. |
val required | Assigns the value to the variable name. |
Example usage
db.set("name", Name {
first: "Tobie",
last: "Morgan Hitchcock",
}).await?;
db.query("CREATE person SET name = $name").await?;
db.query("SELECT * FROM person WHERE name.first = $name.first").await?;
.query()
Runs a set of SurrealQL statements against the database.
Method Syntax
db.query(sql).bind(vars)
Arguments
| Arguments | Description |
|---|
sql required | Specifies the SurrealQL statements. |
vars optional | Assigns variables which can be used in the query. |
Example usage
let sql = "
CREATE person;
SELECT * FROM type::table($table);
";
let mut result = db
.query(sql)
.bind(("table", "person"))
.await?;
let created: Option<Person> = result.take(0)?;
let people: Vec<Person> = result.take(1)?;
.select()
Selects all records in a table, or a specific record, from the database.
Method Syntax
db.select(resource)
Arguments
| Arguments | Description |
|---|
resource required | The table name or a record ID to select. |
Example usage
let people: Vec<Person> = db.select("person").await?;
let person: Option<Person> = db.select(("person", "h5wxrf2ewk8xjxosxtyc")).await?;
Translated query
This function will run the following query in the database:
SELECT * FROM $resource;
.create()
Creates a record in the database.
Method Syntax
db.create(resource).content(data)
Arguments
| Arguments | Description |
|---|
resource required | The table name or the specific record ID to create. |
data optional | The document / record data to insert. |
Example usage
let person: Option<Person> = db.create("person").await?;
let record: Record = db
.create(("person", "tobie"))
.content(Person {
name: "Tobie",
settings: {
active: true,
marketing: true,
},
}).await?;
Translated query
This function will run the following query in the database:
CREATE $resource CONTENT $data;
.update().content()
Updates all records in a table, or a specific record, in the database.
Method Syntax
db.update(resource).content(data)
This function replaces the current document / record data with the specified data.
Arguments
| Arguments | Description |
|---|
resource required | The table name or the specific record ID to create. |
data optional | The document / record data to insert. |
Example usage
let people: Vec<Person> = db.update("person").await?;
let person: Option<Person> = db
.update(("person", "tobie"))
.content(Person {
name: "Tobie",
settings: {
active: true,
marketing: true,
},
}).await?;
Translated query
This function will run the following query in the database:
UPDATE $resource CONTENT $data;
.update().merge()
Modifies all records in a table, or a specific record, in the database.
Method Syntax
db.update(resource).merge(data)
This function merges the current document / record data with the specified data.
Arguments
| Arguments | Description |
|---|
resource required | The table name or the specific record ID to create. |
data optional | The document / record data to insert. |
Example usage
let people: Vec<Person> = db.update("person")
.merge(Document {
updated_at: Datetime::default(),
})
.await?;
let person: Option<Person> = db.update(("person", "tobie"))
.merge(Document {
updated_at: Datetime::default(),
settings: Settings {
active: true,
},
})
.await?;
Translated query
This function will run the following query in the database:
UPDATE $resource MERGE $data;
.update().patch()
Applies JSON Patch changes to all records, or a specific record, in the database.
Method Syntax
db.update(resource).patch(data)
This function patches the current document / record data with the specified JSON Patch data.
Arguments
| Arguments | Description |
|---|
resource required | The table name or the specific record ID to modify. |
data optional | The JSON Patch data with which to modify the records. |
Example usage
let people: Vec<Person> = db.update("person")
.patch(PatchOp::replace("/created_at", Datetime::default()))
.await?;
let person: Option<Person> = db.update(("person", "tobie"))
.patch(PatchOp::replace("/settings/active", false))
.patch(PatchOp::add("/tags", &["developer", "engineer"]))
.patch(PatchOp::remove("/temp"))
.await?;
Translated query
This function will run the following query in the database:
UPDATE $resource PATCH $data;
.delete()
Deletes all records in a table, or a specific record, from the database.
Method Syntax
db.delete(resource)
Arguments
| Arguments | Description |
|---|
resource required | The table name or a record ID to select. |
Example usage
let people: Vec<Person> = db.delete("person").await?;
let person: Option<Person> = db.delete(("person", "h5wxrf2ewk8xjxosxtyc")).await?;
Translated query
This function will run the following query in the database:
DELETE FROM $resource RETURN BEFORE;