relationalai.dsl.ContextSelect
class ContextSelect
ContextSelect
objects are returned by the Context.__enter__()
method.
They are used to select results in query contexts.
ContextSelect
objects are also used in Model.match()
contexts as a variable to which values are conditionally assigned.
Example
Section titled “Example”Both Model.query()
and Model.match()
return Context
objects.
A Context
is a context manager and must be used in a with statement.
ContextSelect
objects are returned by the Context.__enter__()
method, which is called automatically when the with
statement executes.
The ContextSelect
object it returns can be named in the with
statement’s as
clause.
In queries, the ContextSelect
object is used to select the data to be returned.
By convention, we name the ContextSelect
object select
.
You call select()
at the end of the query and pass to it the objects, properties, and variables you want returned in the results:
import relationalai as rai
# =====# SETUP# =====
model = rai.Model("MyModel")Item = model.Type("Item")
with model.rule(): Item.add(id=1).set(name="A", price=10.00) Item.add(id=2).set(name="B", price=10.00) Item.add(id=3).set(name="C", price=20.00)
# =======# EXAMPLE# =======
with model.query() as select: # select is a ContextSelect object item = Item() # Calling select returns the Context object created by model.query(). response = select(item.id, item.name, item.price)
# The query results are assigned to the response.results attribute.print(response.results)# id name price# 0 1 A 10.0# 1 2 B 10.0# 2 3 C 20.0
# Rows for each item filtered by the query are returned in the results. This# means duplicate rows may be returned:
with model.query() as select: item = Item() response = select(item.price)
# There are two rows with 10.00 in the results because there are two two items# with a price of 10.00.print(response.results)# price# 0 10.0# 1 10.0# 2 20.0
# Use select.distinct() to return only unique rows in the results:
with model.query() as select: item = Item() response = select.distinct(item.price)
print(response.results)# price# 0 10.0# 1 20.0
In a Model.match()
context, the ContextSelect
object represents a variable to which values are conditionally assigned.
Give the ContextSelect
object a descriptive name and use the ContextSelect.add()
method to assign values to it:
from relationalai.std import alias
# Compute an item's discount based on its price.with model.query() as select: item = Item() with model.match() as discount: # discount is a ContextSelect object # Items with a price greater than 15 get a 25% discount. with item.price > 15: discount.add(0.25) # Assign 0.25 to discount. # All other items get a 10% discount. with model.case(): discount.add(0.1)
# Compute the discounted price. discounted_price = item.price * (1 - discount)
response = select( item.id, item.name, item.price, alias(discount, "discount"), alias(discounted_price, "discounted_price"), )
print(response.results)# id name price discount discounted_price# 0 1 A 10.0 0.10 9.0# 1 2 B 10.0 0.10 9.0# 2 3 C 20.0 0.25 15.0
See Model.match()
for more information on .match()
contexts.
Methods
Section titled “Methods”Name | Description | Returns |
---|---|---|
.__call__() | Selects query results. Must be called in a query context. | Context |
.distinct() | Selects only distinct rows in the query results. Must be called in a query context. | Context |
.__getattr__() | Accesses properties of values assigned to the ContestSelect . Only used in .match() contexts. | Instance or InstanceProperty |
.add() | Assigns values to the ContextSelect . Only used in .match() contexts. | None |
.add()
Section titled “.add()”ContextSelect.add(item: Any, **kwargs: Any) -> None
Assigns a value to a ContextSelect
object.
May only be called from ContextSelect
objects created in a Model.match()
block.
Parameters
Section titled “Parameters”Name | Type | Description |
---|---|---|
item | Any | The value to assign to the ContextSelect . |
**kwargs | Any | (Optional) Keyword arguments that set context-specific properties on assigned values. |
Returns
Section titled “Returns”None
Example
Section titled “Example”Use .add()
to assign values to a ContextSelect
object in a Model.match()
block:
import relationalai as raifrom relationalai.std import alias
# =====# SETUP# =====
model = rai.Model("MyModel")Item = model.Type("Item")
with model.rule(): Item.add(id=1).set(name="A", price=10.00) Item.add(id=2).set(name="B", price=10.00) Item.add(id=3).set(name="C", price=20.00)
# =======# EXAMPLE# =======
# Compute an item's discount based on its price.with model.query() as select: item = Item() with model.match() as discount: # discount is a ContextSelect object # Items with a price greater than 15 get a 25% discount. with item.price > 15: discount.add(0.25) # Assign 0.25 to discount. # All other items get a 10% discount. with model.case(): discount.add(0.1)
# Compute the discounted price. discounted_price = item.price * (1 - discount)
response = select( item.id, item.name, item.price, alias(discount, "discount"), alias(discounted_price, "discounted_price"), )
print(response.results)# id name price discount discounted_price# 0 1 A 10.0 0.10 9.0# 1 2 B 10.0 0.10 9.0# 2 3 C 20.0 0.25 15.0
Besides Python strings, numbers, dates, datetimes, and Booleans, expressions involving objects and their properties may also be assigned to a ContextSelect
object:
# Declare a Discount type and define some Discount objects.Discount = model.Type("Discount")with model.rule(): Discount.add(rate=0.25).set(code="25OFF") Discount.add(rate=0.10).set(code="10OFF")
# Compute an item's discount based on its price.with model.query() as select: item = Item() with model.match() as discount: # Items with a price greater than 15 get a 25% discount. with item.price > 15: discount.add(Discount(rate=0.25)) # All other items get a 10% discount. with model.case(): discount.add(Discount(rate=0.10))
# Compute the discounted price. Properties of the Discount object can be # accessed directly from the discount variable. discounted_price = item.price * (1 - discount.rate)
response = select( item.name, item.price, alias(discount.code, "discount_code"), alias(discounted_price, "discounted_price"), )
print(response.results)# name price discount_code discounted_price# 0 A 10.0 10OFF 9.0# 1 B 10.0 10OFF 9.0# 2 C 20.0 25OFF 15.0
Optional keyword arguments may be passed to .add()
to set properties on assigned values.
These properties can only be accessed from the ContextSelect
object:
with model.query() as select: item = Item() with model.match() as discount: with item.price > 15: # Assign the Discount object with rate 0.25 to discount and set # the reason to property to provide context for the discount. discount.add(Discount(rate=0.25), reason="Over $15") with model.case(): discount.add(Discount(rate=0.25), reason="$15 or less")
discounted_price = item.price * (1 - discount.rate)
response = select( item.name, item.price, alias(discount.code, "discount_code"), alias(discounted_price, "discounted_price"), alias(discount.reason, "reason"), # Access the reason property set by discount.add(). )
print(response.results)# name price discount_code discounted_price reason# 0 A 10.0 10OFF 9.0 $15 or less# 1 B 10.0 10OFF 9.0 $15 or less# 2 C 20.0 25OFF 15.0 Over $15
The same keyword argument keys must be provided each time you call .add()
in one of the .match()
block’s branches.
Otherwise, an error will be raised.
Properties set in .add()
take precedence over properties set elsewhere with the same name:
with model.query() as select: item = Item() with model.match() as discount: with item.price > 15: # The code property set here takes precedence over the code property # set on the Discount object. discount.add(Discount(rate=0.25), code="SUMMER25") with model.case(): discount.add(Discount(rate=0.10), code="SUMMER10")
discounted_price = item.price * (1 - discount.rate)
response = select( item.name, item.price, alias(discount.code, "discount_code"), alias(discounted_price, "discounted_price"), )
print(response.results)# name price discount_code discounted_price# 0 A 10.0 SUMMER10 9.0# 1 B 10.0 SUMMER10 9.0# 2 C 20.0 SUMMER25 15.0
See Model.match()
for more information on .match()
contexts.
.distinct()
Section titled “.distinct()”ContextSelect.distinct(*args: Producer) -> Context
Selects the data to be returned by a query and returns the Context
object whose .__enter__()
method returned the ContextSelect
object.
Only distinct rows are returned.
The query results are assigned to the Context
object’s .results
attribute.
.distinct()
may only be called in a query context.
Parameters
Section titled “Parameters”Name | Type | Description |
---|---|---|
*args | Producer or Python string, number, date, datetime, or Boolean objects. | The objects, properties, and other values to return in query results. |
Returns
Section titled “Returns”A Context
object.
Example
Section titled “Example”Use .distinct()
in a query context to select only distinct rows of data:
import relationalai as rai
# =====# SETUP# =====
model = rai.Model("Books")Book = model.Type("Book")
with model.rule(): Book.add(title="The Illiad", author="Homer") Book.add(title="The Odyssey", author="Homer") Book.add(title="The Aeneid", author="Virgil")
# =======# EXAMPLE# =======
with model.query() as select: book = Book() response = select.distinct(book.author)
# Author names in the results are unique.print(response.results)# author# 0 Homer# 1 Virgil
# Without .distinct, select() returns a row for each book, even if multiple books# have the same author. For instance, the following query returns two rows for# Homer because there are two books authored by him.
with model.query() as select: book = Book() response = select(book.author)
print(response.results)# author# 0 Homer# 1 Homer# 2 Virgil
.__call__()
Section titled “.__call__()”ContextSelect.__call__(*args: Producer) -> Context
Selects the data to be returned in a model.query()
block and returns the Context
object created by model.query()
.
The query results are assigned to the Context
object’s .results
attribute.
ContextSelect
objects may only be called in a query context.
Parameters
Section titled “Parameters”Name | Type | Description |
---|---|---|
*args | Producer or Python string, number, date, datetime, or Boolean objects. | The objects, properties, and other values to return in query results. |
Returns
Section titled “Returns”A Context
object.
Example
Section titled “Example”Call a ContextSelect
object in a query context to select the data returned by the query:
import relationalai as rai
# =====# SETUP# =====
model = rai.Model("Books")Book = model.Type("Book")NonFiction = model.Type("NonFiction")Fiction = model.Type("Fiction")Horror = model.Type("Horror")Fantasy = model.Type("Fantasy")
with model.rule(): Book.add(Fiction, Horror, title="It", author="Stephen King", year=1986) Book.add(Fiction, Fantasy, title="The Dark Tower", author="Stephen King", year=1982) Book.add(NonFiction, title="On Writing", author="Stephen King", year=2000)
# =======# EXAMPLE# =======
with model.query() as select: # select is a ContextSelect object. book = Book() # response is the Context object returned by model.query(). response = select(book.title, book.author, book.year)
# Query results are assigned to the response.results attribute.print(response.results)# title author year# 0 It Stephen King 1986# 1 On Writing Stephen King 2000# 2 The Dark Tower Stephen King 1982
# Rows for each book filtered by the query are returned in the results. This# means duplicate rows may be returned:
with model.query() as select: book = Book() response = select(book.author)
# There are two rows for Stephen King in the results because there are three# books authored by him.print(response.results)# author# 0 Stephen King# 1 Stephen King# 2 Stephen King
# Use select.distinct() to return only unique rows in the results:
with model.query() as select: book = Book() response = select.distinct(book.author)
print(response.results)# author# 0 Stephen King
You may call a ContextSelect
object multiple times, but it must have the same number of arguments each time it is called:
with model.query() as select: select("B", 1) # The return value only needs to be assigned on the last call. response = select("A", 2)
print(response.results)# v v2# 0 A 2# 1 B 1
Each call adds rows to the query results.
Calling a ContextSelect
object multiple times lets you select data from different logical branches of a query:
with model.query() as select: book = Book() with NonFiction(book): response = select(book.title, "NonFiction") with Fiction(book): select(book.title, "Fiction") with Horror(book): select(book.title, "Horror") with Fantasy(book): response = select(book.title, "Fantasy")
print(response.results)# title v# 0 It Fiction# 1 It Horror# 2 On Writing NonFiction# 3 The Dark Tower Fantasy# 4 The Dark Tower Fiction
.__getattr__()
Section titled “.__getattr__()”ContextSelect.__getattr__(name: str) -> Instance | InstanceProperty
Gets properties of values assigned to a ContextSelect
object.
May only be called from ContextSelect
objects created in a Model.match()
block.
Parameters
Section titled “Parameters”Name | Type | Description |
---|---|---|
name | str | The name of the property to get. |
Returns
Section titled “Returns”An Instance
or an InstanceProperty
.
Example
Section titled “Example”.__getattr__()
is called when you access an attribute of a ContextSelect
object using the dot (.
) operator.
It returns properties of values assigned to the ContextSelect
object:
import relationalai as raifrom relationalai.std import alias
# =====# SETUP# =====
model = rai.Model("MyModel")Item = model.Type("Item")
with model.rule(): Item.add(id=1).set(name="A", price=10.00) Item.add(id=2).set(name="B", price=10.00) Item.add(id=3).set(name="C", price=20.00)
# =======# EXAMPLE# =======
# Compute an item's discount based on its price.with model.query() as select: item = Item() with model.match() as discount: # discount is a ContextSelect object # Items with a price greater than 15 get a 25% discount. with item.price > 15: discount.add(0.25, reason="Over $15") # All other items get a 10% discount. with model.case(): discount.add(0.1, reason="$15 or less")
# Compute the discounted price. discounted_price = item.price * (1 - discount)
response = select( item.id, item.name, item.price, alias(discount, "discount"), alias(discounted_price, "discounted_price"), # discount.reason accesses the reason property set in discount.add(). alias(discount.reason, "reason"), )
print(response.results)# id name price discount discounted_price reason# 0 1 A 10.0 0.10 9.0 $15 or less# 1 2 B 10.0 0.10 9.0 $15 or less# 2 3 C 20.0 0.25 15.0 Over $15
If the value assigned to the ContextSelect
is a Producer
, such as an Instance
or an InstanceProperty
, then .__getattr__()
may also return properties of the Producer
set elsewhere in the model:
# Declare a Discount type and define some Discount objects.Discount = model.Type("Discount")with model.rule(): Discount.add(rate=0.25).set(code="25OFF") Discount.add(rate=0.10).set(code="10OFF")
# Compute an item's discount based on its price.with model.query() as select: item = Item() with model.match() as discount: # Items with a price greater than 15 get a 25% discount. with item.price > 15: discount.add(Discount(rate=0.25)) # All other items get a 10% discount. with model.case(): discount.add(Discount(rate=0.10))
# Compute the discounted price. Properties of the Discount object can be # accessed directly from the discount variable. discounted_price = item.price * (1 - discount.rate)
response = select( item.name, item.price, alias(discount.code, "discount_code"), alias(discounted_price, "discounted_price"), )
print(response.results)# name price discount_code discounted_price# 0 A 10.0 10OFF 9.0# 1 B 10.0 10OFF 9.0# 2 C 20.0 25OFF 15.0
Properties set in ContextSelect.add()
take precedence over properties set elsewhere with the same name:
with model.query() as select: item = Item() with model.match() as discount: with item.price > 15: # The code property set here takes precedence over the code property # set on the Discount object. discount.add(Discount(rate=0.25), code="SUMMER25") with model.case(): discount.add(Discount(rate=0.10), code="SUMMER10")
discounted_price = item.price * (1 - discount.rate)
response = select( item.name, item.price, alias(discount.code, "discount_code"), alias(discounted_price, "discounted_price"), )
print(response.results)# name price discount_code discounted_price# 0 A 10.0 SUMMER10 9.0# 1 B 10.0 SUMMER10 9.0# 2 C 20.0 SUMMER25 15.0
See Model.match()
for more information on .match()
contexts.