The SurrealDB SDK for Rust enables simple and advanced querying of a remote or embedded database from a browser or from server-side code. Remote connections automatically reconnect when the connection is terminated.
First, create a new project using cargo new and add the SurrealDB SDK to your dependencies:
cargoadd surrealdb
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.
useserde::{Deserialize,Serialize};usesurrealdb::engine::remote::ws::Ws;usesurrealdb::opt::auth::Root;usesurrealdb::sql::Thing;usesurrealdb::Surreal;#[derive(Debug, Serialize)]structName<'a>{
first:&'astr,
last:&'astr,}#[derive(Debug, Serialize)]structPerson<'a>{
title:&'astr,
name:Name<'a>,
marketing:bool,}#[derive(Debug, Serialize)]structResponsibility{
marketing:bool,}#[derive(Debug, Deserialize)]structRecord{#[allow(dead_code)]
id:Thing,}#[tokio::main]asyncfnmain()->surrealdb::Result<()>{// Connect to the serverlet 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 idlet created:Vec<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 idlet updated:Option<Record>= db
.update(("person","jaime")).merge(Responsibility{ marketing:true}).await?;dbg!(updated);// Select all people recordslet people:Vec<Record>= db.select("person").await?;dbg!(people);// Perform a custom advanced querylet 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:
cargoadd serde --features derive
cargoadd 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
SDK methods
The Rust SDK comes with a number of built-in functions.
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.
staticDB:Lazy<Surreal<Client>>=Lazy::new(Surreal::init);#[tokio::main]asyncfnmain()->surrealdb::Result<()>{// Connect to the databaseDB.connect::<Wss>("cloud.surrealdb.com").await?;// Select a namespace + databaseDB.use_ns("test").use_db("test").await?;// Create or update a specific recordlet tobie:Option<Record>=DB.update(("person","tobie")).content(Person{ name:"Tobie"}).await?;Ok(())}
db.connect(endpoint)
Connects to a local or remote database endpoint.
Arguments
Description
endpointRequired
The database endpoint to connect to.
// Connect to a local endpointDB.connect::<Ws>("127.0.0.1:8000").await?;// Connect to a remote endpointDB.connect::<Wss>("cloud.surrealdb.com").await?;
Surreal::new::<T>(endpoint)
Connects to a local or remote database endpoint.
Arguments
Description
endpointRequired
The database endpoint to connect to.
let db =Surreal::new::<Ws>("127.0.0.1:8000").await?;
db.use_ns(ns).use_db(db)
Switch to a specific namespace and database.
Arguments
Description
nsRequired
Switches to a specific namespace.
dbRequired
Switches to a specific database.
db.use_ns("test").use_db("test").await?;
db.signup(credentials)
Signs up to a specific authentication scope.
Arguments
Description
credentialsRequired
Variables used in a signup query.
useserde::Serialize;usesurrealdb::opt::auth::Scope;#[derive(Serialize)]structCredentials<'a>{
email:&'astr,
pass:&'astr,}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();
db.signin(credentials)
Signs in to a specific authentication scope.
Arguments
Description
credentialsRequired
Variables used in a signin query.
useserde::Serialize;usesurrealdb::opt::auth::Scope;#[derive(Serialize)]structCredentials<'a>{
email:&'astr,
pass:&'astr,}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();
db.invalidate()
Invalidates the authentication for the current connection.
db.invalidate().await?;
db.authenticate(token)
Authenticates the current connection with a JWT token.
Arguments
Description
tokenRequired
The JWT authentication token.
db.authenticate(jwt).await?;
db.set(key, val)
Assigns a value as a parameter for this connection.
Arguments
Description
keyRequired
Specifies the name of the variable.
valRequired
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?;
db.query(sql).bind(vars)
Runs a set of SurrealQL statements against the database.
Arguments
Description
sqlRequired
Specifies the SurrealQL statements.
varsOptional
Assigns variables which can be used in the query.
// Run some querieslet sql ="
CREATE person;
SELECT * FROM type::table($table);
";letmut result = db
.query(sql).bind(("table","person")).await?;// Get the first result from the first querylet created:Option<Person>= result.take(0)?;// Get all of the results from the second querylet people:Vec<Person>= result.take(1)?;
db.select(resource)
Selects all records in a table, or a specific record, from the database.
Arguments
Description
resourceRequired
The table name or a record ID to select.
// Select all records from a tablelet people:Vec<Person>= db.select("person").await?;// Select a specific record from a tablelet person:Option<Person>= db.select(("person","h5wxrf2ewk8xjxosxtyc")).await?;
This function will run the following query in the database:
SELECT*FROM$resource;
db.create(resource).content(data)
Creates a record in the database.
Arguments
Description
resourceRequired
The table name or the specific record ID to create.
dataOptional
The document / record data to insert.
// Create a record with a random IDlet people:Vec<Person>= db.create("person").await?;// Create a record with a specific IDlet record: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$resourceCONTENT$data;
db.update(resource).content(data)
Updates all records in a table, or a specific record, in the database.
This function replaces the current document / record data with the specified data.
Arguments
Description
resourceRequired
The table name or the specific record ID to update.
dataOptional
The document / record data to insert.
// Update all records in a tablelet people:Vec<Person>= db.update("person").await?;// Update a record with a specific IDlet 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$resourceCONTENT$data;
db.update(resource).merge(data)
Modifies all records in a table, or a specific record, in the database.
This function merges the current document / record data with the specified data.
Arguments
Description
resourceRequired
The table name or the specific record ID to change
dataOptional
The document / record data to insert.
// Update all records in a tablelet people:Vec<Person>= db.update("person").merge(Document{
updated_at:Datetime::default(),}).await?;// Update a record with a specific IDlet 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$resourceMERGE$data;
db.update(resource).patch(data)
Applies JSON Patch changes to all records, or a specific record, in the database.
This function patches the current document / record data with the specified JSON Patch data.
Arguments
Description
resourceRequired
The table name or the specific record ID to modify.
dataOptional
The JSON Patch data with which to modify the records.
// Update all records in a tablelet people:Vec<Person>= db.update("person").patch(PatchOp::replace("/created_at",Datetime::default())).await?;// Update a record with a specific IDlet 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;
db.delete(resource)
Deletes all records in a table, or a specific record, from the database.
Arguments
Description
resourceRequired
The table name or a record ID to select.
// Delete all records from a tablelet people:Vec<Person>= db.delete("person").await?;// Delete a specific record from a tablelet person:Option<Person>= db.delete(("person","h5wxrf2ewk8xjxosxtyc")).await?;
This function will run the following query in the database: