Materialized Views API Reference¶
This module provides support for creating and managing materialized views in SurrealDB for improved query performance on aggregated data.
Core Classes¶
- class surrealengine.materialized_view.MaterializedView(name, query, refresh_interval=None, document_class=None, aggregations=None, select_fields=None)[source]¶
Bases:
objectMaterialized view for SurrealDB.
This class represents a materialized view in SurrealDB, which is a precomputed view of data that can be used to improve query performance for frequently accessed aggregated data.
- name¶
The name of the materialized view
- query¶
The query that defines the materialized view
- refresh_interval¶
The interval at which the view is refreshed
- document_class¶
The document class that the view is based on
- aggregations¶
Dictionary of field names and aggregation functions
- select_fields¶
List of fields to select (if None, selects all fields)
- __init__(name, query, refresh_interval=None, document_class=None, aggregations=None, select_fields=None)[source]¶
Initialize a new MaterializedView.
- Parameters:
name (str) – The name of the materialized view
query (QuerySet) – The query that defines the materialized view
refresh_interval (str) – The interval at which the view is refreshed (e.g., “1h”, “30m”)
document_class (Type['Document']) – The document class that the view is based on
aggregations (Dict[str, Aggregation]) – Dictionary of field names and aggregation functions
select_fields (List[str]) – List of fields to select (if None, selects all fields)
- async create(connection=None, overwrite=False, if_not_exists=False)[source]¶
Create the materialized view in the database.
- create_sync(connection=None, overwrite=False, if_not_exists=False)[source]¶
Create the materialized view in the database synchronously.
- async drop(connection=None)[source]¶
Drop the materialized view from the database.
- Parameters:
connection – The database connection to use (optional)
- drop_sync(connection=None)[source]¶
Drop the materialized view from the database synchronously.
- Parameters:
connection – The database connection to use (optional)
- async refresh(connection=None)[source]¶
Manually refresh the materialized view.
DEPRECATED: SurrealDB views derived from TABLES are live and do not need manual refresh. This method will be removed in a future version.
- Parameters:
connection – The database connection to use (optional)
- refresh_sync(connection=None)[source]¶
Manually refresh the materialized view.
DEPRECATED: SurrealDB views derived from TABLES are live and do not need manual refresh. This method will be removed in a future version.
- Parameters:
connection – The database connection to use (optional)
- property objects: QuerySet¶
Get a QuerySet for querying the materialized view.
- Returns:
A QuerySet for querying the materialized view
- async execute_raw_query(connection=None)[source]¶
Execute a raw query against the materialized view.
This is a workaround for the “no decoder for tag” error that can occur when querying materialized views using the objects property.
- Parameters:
connection – The database connection to use (optional)
- Returns:
The query results
- execute_raw_query_sync(connection=None)[source]¶
Execute a raw query against the materialized view synchronously.
This is a workaround for the “no decoder for tag” error that can occur when querying materialized views using the objects property.
- Parameters:
connection – The database connection to use (optional)
- Returns:
The query results
Aggregation Functions¶
Base Aggregation¶
- class surrealengine.materialized_view.Aggregation(field=None)[source]¶
Bases:
objectBase class for aggregation functions.
This class represents an aggregation function that can be used in a materialized view. Subclasses should implement the __str__ method to return the SurrealQL representation of the aggregation function.
Statistical Aggregations¶
- class surrealengine.materialized_view.Count(field=None)[source]¶
Bases:
AggregationCount aggregation function.
This class represents the count() aggregation function in SurrealQL.
- class surrealengine.materialized_view.Mean(field=None)[source]¶
Bases:
AggregationMean aggregation function.
This class represents the math::mean() aggregation function in SurrealQL.
- class surrealengine.materialized_view.Sum(field=None)[source]¶
Bases:
AggregationSum aggregation function.
This class represents the math::sum() aggregation function in SurrealQL.
- class surrealengine.materialized_view.Min(field=None)[source]¶
Bases:
AggregationMin aggregation function.
This class represents the math::min() aggregation function in SurrealQL.
- class surrealengine.materialized_view.Max(field=None)[source]¶
Bases:
AggregationMax aggregation function.
This class represents the math::max() aggregation function in SurrealQL.
- class surrealengine.materialized_view.Median(field=None)[source]¶
Bases:
AggregationMedian aggregation function.
This class represents the math::median() aggregation function in SurrealQL.
- class surrealengine.materialized_view.StdDev(field=None)[source]¶
Bases:
AggregationStandard deviation aggregation function.
This class represents the math::stddev() aggregation function in SurrealQL.
- class surrealengine.materialized_view.Variance(field=None)[source]¶
Bases:
AggregationVariance aggregation function.
This class represents the math::variance() aggregation function in SurrealQL.
- class surrealengine.materialized_view.Percentile(field=None, percentile=50)[source]¶
Bases:
AggregationPercentile aggregation function.
This class represents the math::percentile() aggregation function in SurrealQL.
Collection Aggregations¶
- class surrealengine.materialized_view.Distinct(field=None)[source]¶
Bases:
AggregationDistinct aggregation function.
This class represents a distinct-of-values across grouped rows. Safe for scalar fields by wrapping each row’s value in an array first.
- class surrealengine.materialized_view.GroupConcat(field=None, separator=', ')[source]¶
Bases:
AggregationGroup concatenation aggregation function.
This class represents a custom aggregation function that concatenates values with a separator.
Usage Examples¶
Basic Materialized View¶
from surrealengine import Document, StringField, IntField, DateTimeField
from surrealengine.materialized_view import MaterializedView, Count, Mean
class Order(Document):
customer_id = StringField(required=True)
amount = DecimalField(required=True)
status = StringField(required=True)
created_at = DateTimeField(auto_now_add=True)
# Create a materialized view for order statistics
order_stats = MaterializedView(
name="order_statistics",
query=Order.objects.group_by("customer_id"),
aggregations={
"total_orders": Count(),
"avg_order_amount": Mean("amount"),
"total_spent": Sum("amount")
},
refresh_interval="1h"
)
# Create the view in the database
await order_stats.create()
Document-Based Materialized Views¶
# Create materialized view using Document class method
customer_summary = Order.create_materialized_view(
name="customer_summary",
query=Order.objects.filter(status="completed").group_by("customer_id"),
aggregations={
"completed_orders": Count(),
"total_revenue": Sum("amount"),
"avg_order_value": Mean("amount"),
"last_order_date": Max("created_at")
},
refresh_interval="30m"
)
await customer_summary.create()
Advanced Aggregations¶
from surrealengine.materialized_view import (
Percentile, StdDev, ArrayCollect, GroupConcat
)
# Advanced statistics view
advanced_stats = MaterializedView(
name="advanced_order_stats",
query=Order.objects.group_by("status"),
aggregations={
"order_count": Count(),
"amount_p95": Percentile("amount", 95),
"amount_std": StdDev("amount"),
"customer_list": ArrayCollect("customer_id"),
"customer_names": GroupConcat("customer_name", separator=", ")
}
)
Time-Based Materialized Views¶
# Daily sales summary
daily_sales = MaterializedView(
name="daily_sales",
query=Order.objects.group_by("DATE(created_at)"),
aggregations={
"daily_revenue": Sum("amount"),
"daily_orders": Count(),
"unique_customers": Distinct("customer_id")
},
refresh_interval="1h"
)
Querying Materialized Views¶
# Query the materialized view
stats = await order_stats.query()
for row in stats:
print(f"Customer {row['customer_id']}: {row['total_orders']} orders")
# Query with filters
high_value_customers = await order_stats.query(
filter_condition="total_spent > 1000"
)
# Get view metadata
info = await order_stats.info()
print(f"View last refreshed: {info['last_refresh']}")
Managing Materialized Views¶
# Refresh view manually
await order_stats.refresh()
# Update view definition
await order_stats.update(
aggregations={
"total_orders": Count(),
"avg_order_amount": Mean("amount"),
"max_order_amount": Max("amount") # Added new aggregation
}
)
# Drop view
await order_stats.drop()
# Check if view exists
exists = await order_stats.exists()
Integration with Query Pipeline¶
from surrealengine.aggregation import AggregationPipeline
# Create aggregation pipeline that can be used for materialized views
pipeline = AggregationPipeline(Order) \\
.match(status="completed") \\
.group_by("customer_id") \\
.aggregate(
total_spent=Sum("amount"),
order_count=Count(),
avg_amount=Mean("amount")
)
# Create materialized view from pipeline
customer_stats = MaterializedView.from_pipeline(
name="customer_stats_mv",
pipeline=pipeline,
refresh_interval="2h"
)
await customer_stats.create()
Performance Monitoring¶
# Monitor view performance
async def monitor_view_performance():
views = [order_stats, customer_summary, daily_sales]
for view in views:
info = await view.info()
print(f"View: {view.name}")
print(f" Size: {info.get('size', 'Unknown')}")
print(f" Last refresh: {info.get('last_refresh', 'Unknown')}")
print(f" Refresh duration: {info.get('refresh_duration', 'Unknown')}")
print()
await monitor_view_performance()