First, create a new project using cargo new and add the SurrealDB SDK to your dependencies:
cargo add surrealdb
Open src/main.rs and replace everything in there with the following code to try out some basic operations using the SurrealDB SDK.
use serde::{Deserialize, Serialize}; use surrealdb::engine::remote::ws::Ws; use surrealdb::opt::auth::Root; use surrealdb::sql::Thing; use surrealdb::Surreal; struct Name<'a> { first: &'a str, last: &'a str, } struct Person<'a> { title: &'a str, name: Name<'a>, marketing: bool, } struct Responsibility { marketing: bool, } struct Record { id: Thing, } async fn main() -> surrealdb::Result<()> { // Connect to the server let db = Surreal::new::<Ws>("127.0.0.1:8000").await?; // Signin as a namespace, database, or root user db.signin(Root { username: "root", password: "root", }) .await?; // Select a specific namespace / database db.use_ns("test").use_db("test").await?; // Create a new person with a random id let created: Option<Record> = db .create("person") .content(Person { title: "Founder & CEO", name: Name { first: "Tobie", last: "Morgan Hitchcock", }, marketing: true, }) .await?; dbg!(created); // Update a person record with a specific id let updated: Option<Record> = db .update(("person", "jaime")) .merge(Responsibility { marketing: true }) .await?; dbg!(updated); // Select all people records let people: Vec<Record> = db.select("person").await?; dbg!(people); // Perform a custom advanced query let groups = db .query("SELECT marketing, count() FROM type::table($table) GROUP BY marketing") .bind(("table", "person")) .await?; dbg!(groups); Ok(()) }
To run the example above, you will need to add the following additional dependencies:
cargo add serde --features derive cargo add tokio --features macros,rt-multi-thread
Then make sure your SurrealDB server is running on 127.0.0.1:8000 and run your app from the command line with:
cargo run
The Rust SDK comes with a number of built-in functions.
Function | Description |
---|---|
Surreal::init() | Initialises a static database engine |
db.connect(endpoint) | Connects to a specific database endpoint, saving the connection on the static client |
Surreal::new::<T>(endpoint) | Connects to a local or remote database endpoint |
db.use_ns(namespace).use_db(database) | Switch to a specific namespace and database |
db.signup(credentials) | Signs up a user to a specific authentication scope |
db.signin(credentials) | Signs this connection in to a specific authentication scope |
db.invalidate() | Invalidates the authentication for the current connection |
db.authenticate(token) | Authenticates the current connection with a JWT token |
db.set(key, val) | Assigns a value as a parameter for this connection |
db.query(sql) | Runs a set of SurrealQL statements against the database |
db.select(resource) | Selects all records in a table, or a specific record |
db.select(resource).live() | Initiate live queries for live stream of notifications |
db.create(resource).content(data) | Creates a record in the database |
db.update(resource).content(data) | Updates all records in a table, or a specific record |
db.update(resource).merge(data) | Modifies all records in a table, or a specific record |
db.update(resource).patch(data) | Applies JSON Patch changes to all records in a table, or a specific record |
db.delete(resource) | Deletes all records, or a specific record |
.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 SyntaxSurreal::init()
static DB: LazyLock<Surreal<Client>> = LazyLock::new(Surreal::init); async fn main() -> surrealdb::Result<()> { // Connect to the database DB.connect::<Wss>("cloud.surrealdb.com").await?; // Select a namespace + database DB.use_ns("test").use_db("test").await?; // Create or update a specific record let tobie: Option<Record> = DB .update(("person", "tobie")) .content(Person { name: "Tobie" }) .await?; Ok(()) }
.connect()
Connects to a local or remote database endpoint.
Method Syntaxdb.connect(endpoint)
Arguments | Description | ||
---|---|---|---|
endpoint required | The database endpoint to connect to. |
// Connect to a local endpoint DB.connect::<Ws>("127.0.0.1:8000").await?; // Connect to a remote endpoint DB.connect::<Wss>("cloud.surrealdb.com").await?;
.new()
Connects to a local or remote database endpoint.
Method SyntaxSurreal::new::<T>(endpoint)
Arguments | Description | ||
---|---|---|---|
endpoint required | The database endpoint to connect to. |
let db = Surreal::new::<Ws>("127.0.0.1:8000").await?;
.use_ns()
and .use_db()
Switch to a specific namespace and database.
Method Syntaxdb.use_ns(ns).use_db(db)
Arguments | Description | ||
---|---|---|---|
ns required | Switches to a specific namespace. | ||
db required | Switches to a specific database. |
db.use_ns("test").use_db("test").await?;
.signup()
Signs up to a specific authentication scope.
Method Syntaxdb.signup(credentials)
Arguments | Description | ||
---|---|---|---|
credentials required | Variables used in a signup query. |
use serde::Serialize; use surrealdb::opt::auth::Scope; struct Credentials<'a> { email: &'a str, pass: &'a str, } let jwt = db.signup(Scope { namespace: "test", database: "test", scope: "user", params: Credentials { email: "info@surrealdb.com", pass: "123456", }, }).await?; // ⚠️: It is important to note that the token should be handled securely and protected from unauthorized access. let token = jwt.as_insecure_token();
.signin()
Signs in to a specific authentication scope.
Method Syntaxdb.signin(credentials)
Arguments | Description | ||
---|---|---|---|
credentials required | Variables used in a signin query. |
use serde::Serialize; use surrealdb::opt::auth::Scope; struct Credentials<'a> { email: &'a str, pass: &'a str, } let jwt = db.signin(Scope { namespace: "test", database: "test", scope: "user", params: Credentials { email: "info@surrealdb.com", pass: "123456", }, }).await?; // ⚠️: It is important to note that the token should be handled securely and protected from unauthorized access. let token = jwt.as_insecure_token();
.invalidate()
Invalidates the authentication for the current connection.
Method Syntaxdb.invalidate(credentials)
db.invalidate().await?;
.authenticate()
Authenticates the current connection with a JWT token.
Method Syntaxdb.authenticate(token)
Arguments | Description | ||
---|---|---|---|
token required | The JWT authentication token. |
db.authenticate(jwt).await?;
.set()
Assigns a value as a parameter for this connection.
Method Syntaxdb.set(key, val)
Arguments | Description | ||
---|---|---|---|
key required | Specifies the name of the variable. | ||
val required | Assigns the value to the variable name. |
// Assign the variable on the connection db.set("name", Name { first: "Tobie", last: "Morgan Hitchcock", }).await?; // Use the variable in a subsequent query db.query("CREATE person SET name = $name").await?; // Use the variable in a subsequent query db.query("SELECT * FROM person WHERE name.first = $name.first").await?;
.query()
Runs a set of SurrealQL statements against the database.
Method Syntaxdb.query(sql).bind(vars)
Arguments | Description | ||
---|---|---|---|
sql required | Specifies the SurrealQL statements. | ||
vars optional | Assigns variables which can be used in the query. |
// Run some queries let sql = " CREATE person; SELECT * FROM type::table($table); "; let mut result = db .query(sql) .bind(("table", "person")) .await?; // Get the first result from the first query let created: Option<Person> = result.take(0)?; // Get all of the results from the second query let people: Vec<Person> = result.take(1)?;
.select()
Selects all records in a table, or a specific record, from the database.
Method Syntaxdb.select(resource)
Arguments | Description | ||
---|---|---|---|
resource required | The table name or a record ID to select. |
// Select all records from a table let people: Vec<Person> = db.select("person").await?; // Select a specific record from a table let person: Option<Person> = db.select(("person", "h5wxrf2ewk8xjxosxtyc")).await?;
use serde::Deserialize; use surrealdb::engine::remote::ws::Ws; use surrealdb::opt::auth::Root; use surrealdb::sql::Id; use surrealdb::Surreal; // defining your own custom Thing struct and using that in place of `Thing` in the `Id` struct struct CustomThing { id: Id, } struct Person { id: CustomThing, name: String, age: u8, } async fn main() -> surrealdb::Result<()> { // Connect to the database let db = Surreal::new::<Ws>("localhost:8000").await?; // Sign in db.signin(Root { username: "root", password: "root", }) .await?; // Select namespace and database to use db.use_ns("namespace").use_db("database").await?; // Create a person db.query("CREATE person:john SET name = 'John Doe', age = 25").await?.check()?; // Query that person let john: Option<Person> = db.select(("person", "john")).await?; dbg!(john); Ok(()) }
This function will run the following query in the database:
SELECT * FROM $resource;
.select().live()
Initiate live queries for live stream of notifications.
Method Syntaxdb.select(resource).live()
Arguments | Description | ||
---|---|---|---|
resource required | The table name or a record ID to select. |
// Select the "person" table and listen for live updates. let mut stream = db.select("person").live().await?; // Process updates as they come in. while let Some(result) = stream.next().await { // Do something with the notification handle(result); } // Handle the result of the live query notification fn handle(result: Result<Notification<Person>>) { println!("Received notification: {:?}", result); }
.create()
Creates a record in the database.
Method Syntaxdb.create(resource).content(data)
Arguments | Description | ||
---|---|---|---|
resource required | The table name or the specific record ID to create. | ||
data optional | The document / record data to insert. |
// Create a record with a random ID let person: Option<Person> = db.create("person").await?; // Create a record with a specific ID let record: Option<Record> = db .create(("person", "tobie")) .content(Person { name: "Tobie", settings: { active: true, marketing: true, }, }).await?;
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 Syntaxdb.update(resource).content(data)
NoteThis function replaces the current document / record data with the specified data.
Arguments | Description | ||
---|---|---|---|
resource required | The table name or the specific record ID to create. | ||
data optional | The document / record data to insert. |
// Update all records in a table let people: Vec<Person> = db.update("person").await?; // Update a record with a specific ID let person: Option<Person> = db .update(("person", "tobie")) .content(Person { name: "Tobie", settings: { active: true, marketing: true, }, }).await?;
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 Syntaxdb.update(resource).merge(data)
NoteThis function merges the current document / record data with the specified data.
Arguments | Description | ||
---|---|---|---|
resource required | The table name or the specific record ID to create. | ||
data optional | The document / record data to insert. |
// Update all records in a table let people: Vec<Person> = db.update("person") .merge(Document { updated_at: Datetime::default(), }) .await?; // Update a record with a specific ID let person: Option<Person> = db.update(("person", "tobie")) .merge(Document { updated_at: Datetime::default(), settings: Settings { active: true, }, }) .await?;
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 Syntaxdb.update(resource).patch(data)
NoteThis function patches the current document / record data with the specified JSON Patch data.
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. |
// Update all records in a table let people: Vec<Person> = db.update("person") .patch(PatchOp::replace("/created_at", Datetime::default())) .await?; // Update a record with a specific ID 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?;
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 Syntaxdb.delete(resource)
Arguments | Description | ||
---|---|---|---|
resource required | The table name or a record ID to select. |
// Delete all records from a table let people: Vec<Person> = db.delete("person").await?; // Delete a specific record from a table let person: Option<Person> = db.delete(("person", "h5wxrf2ewk8xjxosxtyc")).await?;
This function will run the following query in the database:
DELETE FROM $resource RETURN BEFORE;