Getting Started¶
This guide will help you get up and running with SurrealEngine quickly.
Installation¶
Install SurrealEngine using pip:
pip install surrealengine
Or with all optional dependencies:
pip install surrealengine[all]
Prerequisites¶
You’ll need a SurrealDB instance running. The easiest way is with Docker:
# Start SurrealDB
docker run --rm --pull always -p 8000:8000 \
surrealdb/surrealdb:latest \
start --user root --pass root
Or using the SurrealDB binary:
surreal start --user root --pass root
Your First SurrealEngine Application¶
Async Application¶
Here’s a complete async example:
import asyncio
from surrealengine import (
Document, StringField, IntField,
create_connection
)
# Define your document model
class User(Document):
name = StringField(required=True)
email = StringField(required=True)
age = IntField(min_value=0)
class Meta:
collection = "users"
async def main():
# Create connection
connection = create_connection(
url="ws://localhost:8000/rpc",
namespace="myapp",
database="mydb",
username="root",
password="root",
async_mode=True,
make_default=True
)
await connection.connect()
print("✓ Connected to SurrealDB")
# Create table
await User.create_table()
print("✓ Created users table")
# Create a user
user = User(
name="Alice",
email="alice@example.com",
age=30
)
await user.save()
print(f"✓ Created user: {user.id}")
# Query users
users = await User.objects.all()
print(f"✓ Found {len(users)} users")
# Filter users
alice = await User.objects.filter(name="Alice").first()
print(f"✓ Found Alice: {alice.email}")
# Update user
await alice.update(age=31)
print(f"✓ Updated Alice's age to {alice.age}")
# Delete user
await alice.delete()
print("✓ Deleted Alice")
if __name__ == "__main__":
asyncio.run(main())
Synchronous Application¶
For synchronous applications, use the sync API:
from surrealengine import (
Document, StringField, IntField,
create_connection
)
class User(Document):
name = StringField(required=True)
email = StringField(required=True)
age = IntField(min_value=0)
class Meta:
collection = "users"
def main():
# Create synchronous connection
connection = create_connection(
url="ws://localhost:8000/rpc",
namespace="myapp",
database="mydb",
username="root",
password="root",
async_mode=False, # Key parameter for sync
make_default=True
)
connection.connect_sync()
print("✓ Connected to SurrealDB")
# Create table
User.create_table_sync()
print("✓ Created users table")
# Create a user
user = User(name="Bob", email="bob@example.com", age=25)
user.save_sync()
print(f"✓ Created user: {user.id}")
# Query users
users = User.objects.all_sync()
print(f"✓ Found {len(users)} users")
# Filter users
bob = User.objects.filter(name="Bob").first_sync()
print(f"✓ Found Bob: {bob.email}")
# Update user
bob.update_sync(age=26)
print(f"✓ Updated Bob's age to {bob.age}")
if __name__ == "__main__":
main()
Embedded Database (No Server Required)¶
Use an embedded database for local or offline applications:
import asyncio
from surrealengine import Document, StringField, create_connection
class Task(Document):
title = StringField(required=True)
completed = BooleanField(default=False)
class Meta:
collection = "tasks"
async def main():
# Use file-based database (no server needed!)
connection = create_connection(
url="file://./my_app_data",
namespace="myapp",
database="mydb",
async_mode=True,
make_default=True
)
await connection.connect()
# Create and query data
task = Task(title="Learn SurrealEngine")
await task.save()
tasks = await Task.objects.all()
print(f"Tasks: {[t.title for t in tasks]}")
asyncio.run(main())
Connection Options¶
SurrealEngine supports multiple connection schemes:
Remote Server¶
# WebSocket
connection = create_connection(url="ws://localhost:8000/rpc", ...)
# Secure WebSocket
connection = create_connection(url="wss://db.example.com/rpc", ...)
# HTTP
connection = create_connection(url="http://localhost:8000", ...)
# HTTPS
connection = create_connection(url="https://db.example.com", ...)
Embedded Database¶
# In-memory (perfect for testing)
connection = create_connection(url="mem://", ...)
# File-based (persistent storage)
connection = create_connection(url="file:///path/to/db", ...)
# SurrealKV (high-performance)
connection = create_connection(url="surrealkv:///path/to/db", ...)
Core Concepts¶
Documents¶
Documents are the main data models in SurrealEngine:
from surrealengine import Document, StringField, IntField
class Product(Document):
name = StringField(required=True, max_length=100)
price = IntField(min_value=0)
sku = StringField(unique=True)
class Meta:
collection = "products"
schemafull = True
Fields¶
SurrealEngine provides rich field types:
from surrealengine import (
StringField, IntField, FloatField, BoolField,
DateTimeField, ListField, DictField,
ReferenceField, EmailField, URLField
)
class Article(Document):
title = StringField(required=True)
content = StringField()
views = IntField(default=0)
rating = FloatField(min_value=0.0, max_value=5.0)
published = BoolField(default=False)
created_at = DateTimeField(auto_now_add=True)
tags = ListField(StringField())
metadata = DictField()
author = ReferenceField("User")
Querying¶
Django-style query API:
# Get all
products = await Product.objects.all()
# Filter
expensive = await Product.objects.filter(price__gte=100)
# Chain filters
results = await Product.objects.filter(
category="electronics"
).filter(
price__lt=500
).order_by("-price")
# Limit and pagination
page1 = await Product.objects.limit(10).offset(0)
page2 = await Product.objects.page(2, 10)
# Get single object
product = await Product.objects.get(id="product:123")
first = await Product.objects.filter(name="Phone").first()
Common Patterns¶
CRUD Operations¶
# Create
user = User(name="Alice", email="alice@example.com")
await user.save()
# Read
user = await User.objects.get(id=user.id)
users = await User.objects.filter(age__gte=18)
# Update
await user.update(age=31)
# or
user.age = 31
await user.save()
# Delete
await user.delete()
Batch Operations¶
# Bulk create
users = [
User(name=f"User{i}", email=f"user{i}@example.com")
for i in range(100)
]
for user in users:
await user.save()
# Bulk update
await User.objects.filter(status="pending").update(status="active")
# Bulk delete
await User.objects.filter(age__lt=18).delete()
Relationships¶
from surrealengine import ReferenceField
class Comment(Document):
content = StringField(required=True)
author = ReferenceField("User", required=True)
post = ReferenceField("Post", required=True)
class Meta:
collection = "comments"
# Create with references
comment = Comment(
content="Great post!",
author="user:alice",
post="post:123"
)
await comment.save()
# Fetch with related documents
comments = await Comment.objects.fetch("author", "post").all()
print(comments[0].author.name) # Access author's name
Error Handling¶
from surrealengine.exceptions import (
ValidationError,
DoesNotExist,
MultipleObjectsReturned
)
try:
# Validation error
user = User(email="invalid") # Missing required 'name'
await user.save()
except ValidationError as e:
print(f"Validation failed: {e}")
try:
# Does not exist
user = await User.objects.get(id="user:nonexistent")
except DoesNotExist:
print("User not found")
try:
# Multiple objects returned
user = await User.objects.get(name="John") # Multiple Johns
except MultipleObjectsReturned:
print("Multiple users found")
Next Steps¶
Now that you’re familiar with the basics, explore these topics:
Tutorial: Building a Blog Application - In-depth tutorial building a complete application
Document Models - Learn about document models and sync API
Field Types - Explore all available field types
Querying - Master advanced querying techniques
Relationships - Work with graph relationships
Connection Management - Connection pooling and embedded databases
Materialized Views - Create aggregated views
LIVE Queries (Subscriptions) - Real-time subscriptions with LIVE queries
Tips for Success¶
Start with embedded databases for development:
# Development connection = create_connection(url="mem://", ...)
Use schemafull tables for production:
class User(Document): class Meta: schemafull = True
Add indexes for frequently queried fields:
class User(Document): email = StringField(indexed=True, unique=True)
Use validation at the field level:
age = IntField(min_value=0, max_value=150)
Choose sync or async consistently throughout your app
Enable connection pooling for web applications:
connection = create_connection(..., use_pool=True, pool_size=20)
Getting Help¶
Documentation: https://surrealengine.readthedocs.io
GitHub Issues: https://github.com/iristech-systems/surrealengine/issues
Examples: Check the
example_scripts/directory in the repositorySurrealDB Docs: https://surrealdb.com/docs
Troubleshooting¶
Connection Issues¶
If you can’t connect to SurrealDB:
Check that SurrealDB is running:
curl http://localhost:8000/healthVerify credentials are correct
Check namespace and database names
Look for firewall issues
Import Errors¶
If imports fail:
# Reinstall with all dependencies
pip install -U surrealengine[all]
Performance Issues¶
For slow queries:
Add indexes to frequently queried fields
Use
select()oromit()to limit returned fieldsEnable connection pooling
Use
explain()to analyze query plans