Skip to content

relationalai.dsl.Property

class Property

Instances of Property represent properties of a given Type and are analogous to a column of a SQL table. You create them by accessing the property as a Type attribute. Property objects represent the property itself, not its value. For accessing values, see InstanceProperty.

You can create a Property object by accessing it as an attribute of a Type:

import relationalai as rai
model = rai.Model("books")
Book = model.Type("Book")
with model.rule():
Book.add(title="Foundation", author="Isaac Asimov")
# Access the 'title' property of the Book type.
print(type(Book.title))
# Output:
# <class 'relationalai.dsl.Property'>

Property objects cannot be used as variables in a rule or query. Attempting to do so raises an exception:

with model.query() as select:
title = Book.title
author = Book.author
title == "Foundation" # This raises an exception.

To declare a property as multi-valued, use the .has_many() method. This is required for properties derived from Snowflake tables or views where a column contains multiple rows for the same primary key:

import relationalai as rai
model = rai.Model("students")
# Create a Student type from the 'students' table in the 'sandbox.public'
# Snowflake schema. The table has `id`, `course`, and `grade` columns and
# may have multiple rows for each student enrolled in multiple courses.
Student = model.Type("Student", source="sandbox.public.students")
# Declare that the 'course' property is multi-valued.
Student.course.has_many()
# What courses is student 1 enrolled in?
with model.query() as select:
student = Student(id=1)
response = select(student.course)
print(response.results)
# Output:
# course
# 0 Mathematics
# 1 History
# 2 Science

Without declaring Student.course.has_many(), the course property would be treated as single-valued, and the query would return only one course per student.

You can add multiple values to a property using the InstanceProperty.add() or InstanceProperty.extend() methods:

import relationalai as rai
# Create a model named "pets" with Person and Pet types.
model = rai.Model("pets")
Person = model.Type("Person")
Pet = model.Type("Pet")
# Declare that the 'pets' property of the Person type is multi-valued.
Person.pets.has_many()
with model.rule():
alice = Person.add(name="Alice")
# Add one Pet to Alice's 'pets' property.
alice.pets.add(Pet.add(name="Fluffy", type="cat"))
bob = Person.add(name="Bob")
# Add two Pets to Bob's 'pets' property.
bob.pets.extend([
Pet.add(name="Spot", type="dog"),
Pet.add(name="Rex", type="dog")
])

In this example, .has_many() is optional. .add() and .extend() automatically handle the creation of multi-valued properties.

NameTypeDescription
.is_multi_valuedboolWhether the property is multi-valued.
Property.is_multi_valued

Returns True if the property is multi-valued and False otherwise.

Use .is_multi_valued to check if a property is multi-valued:

import relationalai as rai
# Create a model named "pets" with Person and Pet types.
model = rai.Model("people")
Person = model.Type("Person")
Pet = model.Type("Pet")
with model.rule():
# Add a person named Alice with two pets.
alice = Person.add(name="Alice")
alice.pets.extend([
Pet.add(name="Fluffy", type="cat"),
Pet.add(name="Spot", type="dog")
])
# The 'pets' property of the Person type is multi-valued.
print(Person.pets.is_multi_valued)
# Output:
# True
# The 'name' property of the Person type is not multi-valued.
print(Person.name.is_multi_valued)
# Output:
# False
NameDescriptionReturns
.declare()Declare a single-valued property.None
.has_many()Declare a multi-valued property.None
Property.declare() -> None

Declare a single-valued property.

Use .declare() to declare a single-valued property used by a Type:

import relationalai as rai
# Create a model named "MyModel" with a Person type.
model = rai.Model("MyModel")
Person = model.Type("Person")
# Declare Person.name as a single-valued property. NOTE: This is optional
# in most cases.
Person.name.declare()
# Check that the Person.name property is single-valued.
print(Person.name.is_multi_valued)
# False
# Define Person and Pet objects.
with model.rule():
Person.add(name="Alice")
# NOTE: Person.add() automatically creates a single-valued 'name' property
# if Person.name.declare() is missing.

.declare() is optional in most cases. Calling Type.add() or InstanceProperty.set() automatically creates a single-valued property if it hasn’t been declared.

You can use .declare() to avoid the UninitializedPropertyException raised when trying to access a property that has never been set. This can happen, for example, when you define a Type from a Snowflake table and access a property corresponding to a column containing only NULL values:

Employee = model.Type("Employee", source="<db>.<schema>.employees")
# Suppose the 'middle_name' column in the 'employees' table contains only NULL
# values, since it's an optional field and no one has provided their middle name.
# Accessing Employee.middle_name without declaring it raises an
# UninitializedPropertyException, but you can declare it to avoid the exception:
Employee.middle_name.declare()
Property.has_many() -> None

Declare a multi-valued property.

Use .has_many() to declare a multi-valued property:

import relationalai as rai
# Create a model named "PetsModel" with Person and Pet types.
model = rai.Model("PetsModel")
Person = model.Type("Person")
Pet = model.Type("Pet")
# Declare the Person.pets property to be multi-valued. NOTE: This is optional.
Person.pets.has_many()
# Check that the Person.pets property is multi-valued.
print(Person.pets.is_multi_valued)
# True
# Define Person and Pet objects.
with model.rule():
alice = Person.add(name="Alice")
# Note that alice.pets.add() automatically creates a multi-valued pets property
# if the .has_many() declaration is missing.
alice.pets.add(Pet.add(name="Fluffy", type="cat"))
bob = Person.add(name="Bob")
# Like .add(), bob.pets.extend() creates a multi-valued pets property if the
# .has_many() declaration is missing.
bob.pets.extend([
Pet.add(name="Spot", type="dog"),
Pet.add(name="Rex", type="dog")
])

.has_many() is optional in most cases. Calling InstanceProperty.add() or InstanceProperty.extend() automatically creates a multi-valued property if it hasn’t been declared.

The one case where .has_many() is required is when defining a Type from a Snowflake table. By default, properties of objects created from rows in a Snowflake table are single-valued. If you intend to use one of the properties as multi-valued — for example, by adding more values to the property in your model’s rules — you must declare it with .has_many():

import relationalai as rai
model = rai.Model("students")
# Declare a Student type with objects created from the students tables in the
# sandbox.public Snowflake schema.
Student = model.Type("Student", source="sandbox.public.students")
# Declare the email property of the Student type to be multi-valued.
Student.email.has_many()