Data Subscription Creation Examples



Create subscription - for all documents in a collection

Here we create a plain subscription on the Orders collection without any constraints or transformations.
The server will send ALL documents from the Orders collection to a client that connects to this subscription.

name = store.subscriptions.create_for_class(
    Order, SubscriptionCreationOptions(name="OrdersProcessingSubscription")
)
name = store.subscriptions.create_for_options(SubscriptionCreationOptions(query="From Orders"))

Create subscription - filter documents

Here we create a subscription for documents from the Orders collection where the total order revenue is greater than 100. Only documents that match this condition will be sent from the server to a client connected to this subscription.

name = store.subscriptions.create_for_options(
    SubscriptionCreationOptions(
        query=(
            "declare function getOrderLinesSum(doc) {"
            "    var sum = 0;"
            "    for (var i in doc.Lines) {"
            "        sum += doc.Lines[i].PricePerUnit * doc.Lines[i].Quantity;"
            "    }"
            "    return sum;"
            "}"
            "From Orders as o "
            "Where getOrderLinesSum(o) > 100 "
        )
    ),
)

Create subscription - filter and project fields

Here, again, we create a subscription for documents from the Orders collection where the total order revenue is greater than 100. However, this time we only project the document ID and the Total Revenue properties in each object sent to the client.

name = store.subscriptions.create_for_options(
    SubscriptionCreationOptions(
        query="""
        declare function getOrderLinesSum(doc) {
            var sum = 0;
            for (var i in doc.Lines) {
                sum += doc.Lines[i].PricePerUnit * doc.Lines[i].Quantity;
            }
            return sum;
        }
        
        declare function projectOrder(doc) {
            return {
                Id: doc.Id,
                Total: getOrderLinesSum(doc)
            };
        }
        
        From Orders as o
        Where getOrderLinesSum(o) > 100
        Select projectOrder(o)
        """
    )
)

In this subscription, in addition to projecting the document fields,
we also project data from a related document that is loaded using the load method.

name = store.subscriptions.create_for_options(
    SubscriptionCreationOptions(
        query="""
        declare function getOrderLinesSum(doc) {
            var sum = 0;
            for (var i in doc.Lines) {
                sum += doc.Lines[i].PricePerUnit * doc.Lines[i].Quantity;
            }
            return sum;
        }
       
        declare function projectOrder(doc) {
            var employee = load(doc.Employee);
            return {
                Id: doc.Id,
                Total: getOrderLinesSum(doc),
                ShipTo: doc.ShipTo,
                EmployeeName: employee.FirstName + ' ' + employee.LastName
            };
        }
       
        From Orders as o
        Where getOrderLinesSum(o) > 100
        Select projectOrder(o)
        """
    )
)

Create subscription - include documents

Here we create a subscription on the Orders collection, which will send all the Order documents.

In addition, the related Product documents associated with each Order are included in the batch sent to the client. This way, when the subscription worker that processes the batch in the client accesses a Product document, no additional call to the server will be made.

See how to consume this type of subscription here.

store.subscriptions.create_for_class(
    Order,
    SubscriptionCreationOptions(includes=lambda builder: builder.include_documents("Lines[].Product")),
)
store.subscriptions.create_for_options(
    SubscriptionCreationOptions(query="from Orders include Lines[].Product")
)
store.subscriptions.create_for_options(
    SubscriptionCreationOptions(
        query="""
        declare function includeProducts(doc) {
            let includedFields = 0;
            let linesCount = doc.Lines.length;

            for (let i = 0; i < linesCount; i++) {
                includedFields++;
                include(doc.Lines[i].Product);
            }

            return doc;
        }

        from Orders as o select includeProducts(o)
        """
    )
)

Include using builder:

Include statements can be added to the subscription with SubscriptionIncludeBuilder.
This builder is assigned to the includes property in SubscriptionCreationOptions.
It supports methods for including documents as well as counters. These methods can be chained.

To include related documents, use method include_documents.
(See the Builder-syntax tab in the example above).

Include using RQL:

The include statements can be written in two ways:

  1. Use the include keyword at the end of the query, followed by the paths to the fields containing the IDs of the documents to include. It is recommended to prefer this approach whenever possible, both for the clarity of the query and for slightly better performance.
    (See the RQL-path-syntax tab in the example above).

  2. Define the include within a JavaScript function that is called from the select clause.
    (See the RQL-javascript-syntax tab in the example above).

If you include documents when making a projection, the include will search for the specified paths in the projected fields rather than in the original document.

Create subscription - include counters

SubscriptionIncludeBuilder has three methods for including counters:

def include_counter(self, name: str) -> SubscriptionIncludeBuilder: ...

def include_counters(self, *names: str) -> SubscriptionIncludeBuilder: ...

def include_all_counters(self) -> SubscriptionIncludeBuilder: ...

include_counter is used to specify a single counter.
include_counters is used to specify multiple counters.
include_all_counters retrieves all counters from all subscribed documents.

Parameter Type Description
name str The name of a counter. The subscription will include all counters with this name that are contained in the documents the subscription retrieves.
*names str Array of counter names.

The following subscription, which includes multiple counters in the batch sent to the client,
demonstrates how the methods can be chained.

store.subscriptions.create_for_class(
    Order,
    SubscriptionCreationOptions(
        includes=lambda builder: builder
        .include_counter("Likes")
        .include_counters("Pros", "Cons")
    ),
)

Update existing subscription

The subscription definition can be updated after it has been created.
In this example we update the filtering query of an existing subscription named "my subscription".

store.subscriptions.update(SubscriptionUpdateOptions(
    name="My subscription", query="from Products where PricePerUnit > 50"))

Modifying the subscription's name:

In addition to the subscription name, each subscription is assigned a subscription ID when it is created by the server. This ID can be used to identify the subscription, instead of the name, when updating the subscription.

This allows users to change an existing subscription's name by specifying the subscription's ID
and submitting a new string in the name field of SubscriptionUpdateOptions.

my_subscription = store.subscriptions.get_subscription_state("my subscription")

subscription_id = my_subscription.subscription_id

store.subscriptions.update(SubscriptionUpdateOptions(key=subscription_id, name="new name"))