Perform requests lazily
-
Lazy request:
-
You can define a lazy request within a session (e.g. a lazy-query or a lazy-load request)
and defer its execution until actually needed. -
The lazy request definition is stored in the session and a
Lazy
instance is returned.
The request will be sent to the server and executed only when you access the value of this instance.
-
-
Multiple lazy requests:
-
Multiple lazy requests can be defined within the same session.
-
When triggering the deferred execution (whether implicitly or explicitly),
ALL pending lazy requests held up by the session will be sent to the server in a single call.
This can help reduce the number of remote calls made to the server over the network.
-
-
In this page:
Operations that can be executed lazily
Load entities
load loads a document entity from
the database into the session.
Loading entities can be executed lazily.
lazy_employee = (
session
# Add a call to lazily
.advanced.lazily.
# Document will not be loaded from the database here, no server call in made
load("employees/1-A", Employee)
)
employee = lazy_employee.value # 'load' operation is executed here
# The employee entity is now loaded & tracked by the session
Load entities with include
load with include loads
both the document and the specified related document.
Loading entities with include can be executed lazily.
lazy_product = (
session
# Add a call to lazily
.advanced.lazily
# Request to include the related Supplier document
# Documents will Not be loaded from the database here, no server call is made
.include("SupplierId").load("products/1-A")
)
# 'Load with include' operation will be executed here
# Both documents will be retrieved from the database
product = lazy_product.value
# The product entity is now loaded & tracked by the session
# Access the related document, no additional server call is made
supplier = session.load(product.SupplierId)
# The supplier entity is now also loaded & tracked by the session
class Product:
def __init__(self, Id: str = None, Name: str = None, SupplierId: str = None):
self.Id = Id
self.Name = Name
self.SupplierId = SupplierId # The related document ID
Load entities starting with
load_starting_with loads
entities whose ID starts with the specified prefix.
Loading entities with a common prefix can be executed lazily.
lazy_employees = (
session
# Add a call to lazily
.advanced.lazily
# Request to load entities whose ID starts with 'employees/'
# Documents will Not be loaded from the database here, no server call is made
.load_starting_with("employees/")
)
employees = lazy_employees.value # 'load' operation is executed here
# The employee entities is now also loaded & tracked by the session
Conditional load
conditional_load logic is:
- If the entity is already loaded to the session:
no server call is made, the tracked entity is returned. - If the entity is Not already loaded to the session:
the document will be loaded from the server only if the change-vector provided to the method is older than the one in the server (i.e. if the document in the server is newer). - Loading entities conditionally can be executed lazily.
# Create document and get is change-vector:
change_vector: Optional[str] = None
with store.open_session() as session1:
employee = Employee()
session1.store(employee, "employees/1-A")
session1.save_changes()
# Get the tracked entity change-vector
change_vector = session1.advanced.get_change_vector_for(employee)
# Conditionally lazy-load the document
with store.open_session() as session2:
lazy_employee = (
session2
# Add a call to lazily
.advanced.lazily
# Document will Not be loaded from the database here, no server call is made
.conditional_load("employees/1-A", change_vector)
)
loaded_item = lazy_employee.value # 'conditional_load' operation is executed here
employee = loaded_item.entity
# If conditional_load has actually fetched the document from the server (logic described above)
# then the employee entity is now loaded & tracked by the session
Run query
A query can be executed lazily.
Learn more about running queries lazily in lazy queries.
# Define a lazy query:
lazy_employees = (
session.query(object_type=Employee).where_equals("FirstName", "John")
# Add a call to lazily, the query will not be executed here
.lazily()
)
employees = lazy_employees.value # query is executed here
# Note: Since query results are not projected,
# then the resulting employee entities will be tracked by the session.
Get revisions
All methods for getting revisions and their metadata can be executed lazily.
lazy_revisions = (
session.
# Add a call to lazily
advanced.revisions.lazily
# Revisions will Not be fetched here, no sever call is made
.get_for("employees/1-A", Employee)
)
# Usage is the same for the other get revisions methods:
# .get()
# .get_metadata_for()
revisions = lazy_revisions.value # Getting revisions is executed here
Get compare-exchange value
get_compare_exchange_value can be executed lazily.
with store.open_session(
session_options=SessionOptions(transaction_mode=TransactionMode.CLUSTER_WIDE)
) as session:
# Create compare-exchange value:
session.advanced.cluster_transaction.create_compare_exchange_value("someKey", "someValue")
session.save_changes()
# Get the compare-exchange value lazily:
lazy_cmp_xchg = (
session
# Adda a call to lazily
.advanced.cluster_transaction.lazily
# Compare-exchange values will Not be fetched here, no server call is made
.get_compare_exchange_value("someKey")
)
# Usage is the same for the other method:
# .get_compare_exchange_values()
cmp_xchg_value = lazy_cmp_xchg.value # Getting compare-exchange value is executed here
Multiple lazy requests
Execute all requests - implicitly
Accessing the value of ANY of the lazy instances will trigger the execution of ALL pending lazy requests held up by the session, in a SINGLE server call.
# Define multiple lazy requests
lazy_user_1 = session.advanced.lazily.load("users/1-A")
lazy_user_2 = session.advanced.lazily.load("users/2-A")
lazy_employees = session.query(object_type=Employee).lazily()
lazy_products = session.query(object_type=Product).search("Name", "Ch*").lazily()
# Accessing the value of ANY of the lazy instances will trigger
# the execution of ALL pending lazy requests held up by the session
# This is done in a SINGLE server call
user1 = lazy_user_1.value
# ALL the other values are now also available
# No additional server calls are made when accessing these values
user2 = lazy_user_2.value
employees = lazy_employees.value
products = lazy_products.value
Execute all requests - explicitly
Explicitly calling execute_all_pending_lazy_operations
will execute
ALL pending lazy requests held up by the session, in a SINGLE server call.
# Define multiple lazy requests
lazy_user_1 = session.advanced.lazily.load("users/1-A")
lazy_user_2 = session.advanced.lazily.load("users/2-A")
lazy_employees = session.query(object_type=Employee).lazily()
lazy_products = session.query(object_type=Product).search("Name", "Ch*").lazily()
# Explicitly call 'execute_all_pending_lazy_operations'
# ALL pending lazy requests held up by the session will be executed in a SINGLE server call
session.advanced.eagerly.execute_all_pending_lazy_operations()
# ALL values are now available
# No additional server calls are made when accessing the values
user1 = lazy_user_1.value
user2 = lazy_user_2.value
employees = lazy_employees.value
products = lazy_products.value