Skip to content

relationalai.dsl.Type

class Type

Types are used to categorize objects in a model. You declare types using the Model.Type() method, which returns an instance of the Type class.

Use Model.Type() to create a Type object rather than constructing one directly:

import relationalai as rai
model = rai.Model("MyModel")
# Declare Person and Adult types using the model.Type() method. The optional
# source parameter specifies a Snowflake table with source data for objects with
# the given type.
Person = model.Type("Person", source="<db>.<schema>.<table>")
Adult = model.Type("Adult")

See Model.Type() for more information.

NameDescriptionReturns
.__and__()Supports the & operator for defining intersections of types.TypeIntersection
.__call__()Gets a reference to objects with the given type.Instance
.__or__()Supports the | operator for defining unions of types.TypeUnion
.add()Adds a new object with the given type.Instance
.define()Defines properties for a type based on foreign key relationships to other types.None
.extend()Extends the type with all objects from another type.None
.known_properties()Gets all statically known properties of objects with the given type.list[str]
Type.add(
self,
*args: Type | TypeUnion | TypeIntersection,
**kwargs: Any,
) -> Instance

Defines new objects with the given Type and returns an Instance used to reference those objects in a rule or query context.

NameTypeDescription
*argsType, TypeUnion, TypeIntersectionSpecifies additional types to which the object belongs.
**kwargsAnySpecifies properties of the object as key-value pairs.

An Instance object.

Use Type.add() to define a new object with the given type:

import relationalai as rai
# =====
# SETUP
# =====
model = rai.Model("BooksModel")
# Declare a Book type.
Book = model.Type("Book")
# =======
# EXAMPLE
# =======
# Define a Book object with title and author properties.
with model.rule():
Book.add(title="Foundation", author="Isaac Asimov")

You may define an object with multiple types simultaneously by passing additional Type objects as positional parameters:

Fiction = model.type("Fiction")
SciFi = model.Type("SciFi")
with model.rule():
book = Book.add(Fiction, SciFi, title="Foundation", author="Isaac Asimov")

Only properties that uniquely identify the object should be passed to .add(). Non-identifying properties are set using the Instance.set() method.

Properties passed to .add() are hashed to create a unique internal identifier for the object. When you select an Instance object, the unique identifiers of the objects it references are returned:

with model.query() as select:
book = Book()
response = select(book)
print(response.results)
# Output:
# book
# 0 iikm1rGdR3jWQtS2XVUZDg
Type.__and__(self, __value: Any) -> TypeUnion

Supports the & operator for expressing the intersection of two types.

A TypeIntersection object.

import relationalai as rai
# =====
# SETUP
# =====
model = rai.Model("BookModel")
# Declare Book, Fiction, NonFiction, Fantasy, and SciFi types.
Book = model.Type("Book")
Fiction = model.Type("Fiction")
NonFiction = model.Type("NonFiction")
Fantasy = model.Type("Fantasy")
SciFi = model.Type("SciFi")
# Define some book objects.
with model.rule():
Book.add(Fiction, Fantasy, title="The Hobbit", author="J.R.R. Tolkien")
Book.add(Fiction, SciFi, title="Foundation", author="Isaac Asimov")
Book.add(Fiction, SciFi, Fantasy, title="The Dark Tower", author="Stephen King")
# =======
# EXAMPLE
# =======
# Use the & operator to define a TypeIntersection of SciFi and Fantasy.
SciFiFantasy = SciFi & Fantasy
# You can query a TypeIntersection the same way you query a Type.
with model.query() as select:
book = SciFiFantasy()
response = select(book.title, book.author)
# You can also use the & operator to define a TypeIntersection inline.
with model.query() as select:
book = Book(SciFi & Fantasy)
response = select(book.title, book.author)
print(response.results)
# title author
# 0 The Dark Tower Stephen King
# Note that Book(SciFi & Fantasy) is equivalent to Book(SciFi, Fantasy).
with model.query() as select:
book = Book(SciFi, Fantasy)
response = select(book.title, book.author)
print(response.results)
# title author
# 0 The Dark Tower Stephen King
Type.__call__(
self,
*args: Type | TypeUnion | TypeIntersection,
**kwargs: Any,
) -> Instance

Returns an Instance used to reference objects of the given type in a rule or query context.

NameTypeDescription
*argsType, TypeUnion, TypeIntersectionFilter the objects referenced by the returned Instance to those that are also instances of all the specified types. These types are used as additional constraints on the Instance.
**kwargsAnyFilter the objects referenced by the returned Instance to those that have properties matching the specified key-value pairs.

An Instance object.

import relationalai as rai
# =====
# SETUP
# =====
model = rai.Model("BookModel")
# Declare Book, Fiction, and NonFiction types.
Book = model.Type("Book")
Fiction = model.Type("Fiction")
NonFiction = model.Type("NonFiction")
# Define some Book objects.
with model.rule():
Book.add(Fiction, title="Foundation", author="Isaac Asimov")
Book.add(NonFiction, title="Humble Pi", author="Matt Parker")
# =======
# EXAMPLE
# =======
# Call a Type to get an Instance that references objects of that type.
# Properties of objects are accessed as attributes of the Instance.
with model.query() as select:
book = Book()
response = select(book.title)
print(response.results)
# title
# 0 Foundation
# 1 Humble Pi
# You can filter the objects referenced by the returned Instance by passing
# additional types as positional arguments and property values as keyword arguments.
with model.query() as select:
# Get a reference to all Fiction books with the title "Foundation".
book = Book(Fiction, title="Foundation")
response = select(book.author)
print(response.results)
# author
# 0 Isaac Asimov
# The above query is equivalent to the following:
with model.query() as select:
book = Book()
Fiction(book) # Filter for Fiction books.
book.title == "Foundation" # Filter for books with the title "Foundation".
response = select(book.author)
print(response.results)
# author
# 0 Isaac Asimov
# When you pass multiple types as positional arguments, the Instance references
# objects that are instances of all the specified types.
with model.query() as select:
book = Book(Fiction, NonFiction)
response = select(book.title, book.author)
# The response is empty since no books are both Fiction and NonFiction.
print(response.results)
Type.define(self, **kwargs: tuple[Type, str, str]) -> None

Defines properties for a type based on foreign key relationships to other types.

NameTypeDescription
**kwargstuple[Type, str, str]Keyword arguments where keys are the names of the new properties. Values are tuples representing a foreign key relationship, which include:
  1. The related Type.
  2. The name of the foreign key property.
  3. The name of the property in the related type on which the foreign key relationship is based.

None.

Use Type.define() to associate objects of one type with objects of another type based on a foreign key relationship.

For example, an Employee type defined from a Snowflake table might have a department_id property that references Department objects by their id property. You can define a department property for Employee objects that connects them to the related Department objects via the department_id property:

import relationalai as rai
# =====
# SETUP
# =====
model = rai.Model("EmployeesModel")
# Declare Employee and Department types from Snowflake tables.
Employee = model.Type("Employee", source="<db>.<schema>.employees")
Department = model.Type("Department", source="<db>.<schema>.departments")
# =======
# EXAMPLE
# =======
# Define a property named 'department' for Employee objects that connects them
# to Department with the same id as the employee's department_id.
Employee.define(department=(Department, "department_id", "id"))
# Related department objects can be accessed directly in rules and queries using
# the 'department' property.
with model.query() as select:
employee = Employee()
employee.department.name == "Sales"
response = select(employee.name)
print(response.results)
# name
# 0 Jim
# 1 Dwight
# 2 Phyllis
Type.extend(self, *args: Type, **kwargs: Any) -> None

Assigns instances from the types passed to *args to the current Type. Optionally, you can set additional properties on the extended objects by passing keyword arguments.

NameTypeDescription
*argsTypeOne or more Type objects whose instances will be assigned to the current Type.
*kwargsAnyOptional keyword arguments that set additional properties on the objects added to the current Type. These properties apply to all objects being extended.

None.

import relationalai as rai
# =====
# SETUP
# =====
model = rai.Model("BooksModel")
# Declare Book, Fiction, Fantasy, and SciFi types.
Book = model.Type("Book")
Fiction = model.Type("Fiction")
Fantasy = model.Type("Fantasy")
SciFi = model.Type("SciFi")
# =======
# EXAMPLE
# =======
# Extend the Fiction type to include all Fantasy and SciFi objects.
Fiction.extend(Fantasy, SciFi)
# Define some Book objects.
with model.rule():
Book.add(SciFi, name="Foundation", author="Isaac Asimov")
Book.add(Fantasy, name="The Hobbit", author="J.R.R. Tolkien")
# Both books are instances of the Fiction type.
with model.query() as select:
book = Fiction()
response = select(book.name, book.author)
print(response.results)
Type.known_properties() -> list[str]

Returns a list of strings containing the names of all statically known properties of objects with the given Type.

A list of str objects.

Use Type.known_properties() to get the names of properties known to be used by objects of the given type. Known properties are properties that can be statically inferred from a model’s rules. This includes properties imported from a Snowflake table, or set in a rule that directly references the Type.

In the following model, both the name and age properties are known to the Person type:

import relationalai as rai
# =====
# SETUP
# =====
model = rai.Model("PeopleModel")
# Declare Person and Adult types.
Person = model.Type("Person")
Adult = model.Type("Adult")
# Define some Person objects.
with model.rule():
Person.add(name="Alice", age=20)
Person.add(name="Bob", age=15)
# Set the Adult type on Person objects whose age property is at least 18.
with model.rule():
person = Person()
person.age >= 18
person.set(Adult)
# =======
# EXAMPLE
# =======
print(Person.known_properties())
# ['name', 'age']

However, the Adult type does not know about the name or age properties since they inherit those properties indirectly from the Person type:

print(Adult.known_properties())
# []
Type.__or__(self, __value: Any) -> TypeUnion

Supports the | operator for expressing the union of two types.

A TypeUnion object.

import relationalai as rai
# =====
# SETUP
# =====
model = rai.Model("BookModel")
# Declare Book, Fiction, NonFiction, Fantasy, and SciFi types.
Book = model.Type("Book")
Fiction = model.Type("Fiction")
NonFiction = model.Type("NonFiction")
Fantasy = model.Type("Fantasy")
SciFi = model.Type("SciFi")
# Add some book instance to the Book type.
with model.rule():
Book.add(Fiction, Fantasy, title="The Hobbit", author="J.R.R. Tolkien")
Book.add(Fiction, SciFi, title="Foundation", author="Isaac Asimov")
Book.add(NonFiction, title="Humble Pi", author="Matt Parker")
# =======
# EXAMPLE
# =======
# Use the | operator to define a TypeUnion of NonFiction and Fantasy.
NonFictionOrFantasy = NonFiction | Fantasy
# You can query a TypeUnion the same way you query a Type.
with model.query() as select:
book = NonFictionOrFantasy()
response = select(book.title, book.author)
print(response.results)
# title author
# 0 Humble Pi Matt Parker
# 1 The Hobbit J.R.R. Tolkien
# You may also use the | operator to define a TypeUnion inline.
with model.query() as select:
book = Book(NonFiction | Fantasy)
response = select(book.title, book.author)
print(response.results)
# title author
# 0 Humble Pi Matt Parker
# 1 The Hobbit J.R.R. Tolkien