InstanceProperty#

relationalai
#class relationalai.InstanceProperty

InstanceProperty is a subclass of Producer that produces property values within rule and query contexts. They are created by accessing attributes of an Instance.

Methods#

In addition to the methods inherited from Producer, InstanceProperty supports:

NameDescriptionReturns
.or_()Set a default property value on objects lacking a value.InstanceProperty
.in_()Check if the property value is in a collection.Expression
.add()Add a value to a property, creating the property if it doesn’t exist.None
.extend()Extend a multi-valued property with multiple values from an iterable, creating the property if it doesn’t exist.None
.choose()Choose n values from a multi-valued property.tuple of n Instance
.set()Set properties or assigns types to the object associated with the current InstanceProperty.Instance
.has_value()Check if the property has a value and is not None.InstanceProperty

Example#

As producers, instances of InstanceProperty serve as variables in rules or queries that represent property values of objects. You create them by accessing attributes of an Instance:

#import relationalai as rai

# Create a model named "books" with a Book type.
model = rai.Model("books")
Book = model.Type("Book")

# Add some books to the model.
with model.rule():
    # Each call to `Book.add` creates a book with title, author, and year_published properties.
    Book.add(title="Foundation", author="Isaac Asimov", year_published=1951)
    Book.add(title="Foundation and Empire", author="Isaac Asimov", year_published=1952)
    Book.add(title="Dune", author="Frank Herbert")  # Note that year_published is not set.

# Get the names of books authored by Isaac Asimov.
with model.query() as select:
    # Get all books.
    book = Book()
    # InstanceProperty objects are created by accesing an attribute of an Instance, like book.author.
    # Here it is used in an expression to filter books by author.
    book.author == "Isaac Asimov"
    # Select the book.title property to include in the query result.
    response = select(book.title)

print(response.results)
# Output:
#                    title
# 0             Foundation
# 1  Foundation and Empire

Envision this rule executing for each book in the model, with each book passing through the rule’s criteria sequentially:

  1. Book() returns an Instance that produces a Book object.
  2. book.author returns an InstanceProperty for the author’s name. The == operator filters books by comparing book.author to “Isaac Asimov”.
  3. book.title returns an InstanceProperty for the book’s title, which is selected in the query results.

InstanceProperty supports various comparison and mathematical operators such as ==, !=, <, +, -, *, /, and %. The following example demonstrates using the % operator with InstanceProperty to filter books published in an even-numbered year:

## Get books published in an even numbered year.
with model.query() as select:
    book = Book()
    book.year_published % 2 == 0  # Filter books by even year.
    response = select(book.title, book.year_published)

print(response.results)
# Output:
#                    title  year_published
# 0  Foundation and Empire            1952

For the full list of supported operators, see the Producer class documentation.

By default, InstanceProperty outputs None for undefined properties, which may display as NaN in the query’s pandas DataFrame depending on the property’s data type.

## Get the genre and rating of each book.
with model.query() as select:
    book = Book()
    response = select(book.title, book.year_published)

print(response.results)
# Output:
#                    title  year_published
# 0                   Dune             NaN
# 1             Foundation          1951.0
# 2  Foundation and Empire          1952.0

Use .or_() to assign default values to properties lacking explicit values:

#with model.query() as select:
    book = Book()
    response = select(book.title, book.year_published.or_(-1))

print(response.results)
# Output:
#                    title  year_published
# 0                   Dune              -1
# 1             Foundation            1951
# 2  Foundation and Empire            1952

You can check if a property has a value and is not None using .has_value():

## Get books that have a year published.
with model.query() as select:
    book = Book()
    book.year_published.has_value()  # Filter books that have a year published.
    response = select(book.title, book.year_published)

print(response.results)
# Output:
#                    title  year_published
# 0             Foundation            1951
# 1  Foundation and Empire            1952

By default, properties support only a single value, and setting a new value overwrites the previous one. You can create and manage multi-valued properties by using .add() or .extend():

## Add genres to the books.
# genres is a multi-valued property because it is created with Instance.extend().
with model.rule():
    Book(title="Foundation").genres.extend(["Science Fiction"])
    Book(title="Dune").genres.extend(["Science Fiction", "Adventure"])

# Get the genres of all books.
with model.query() as select:
    book = Book()
    # Select the title and genres properties of the books.
    # `.or_()` sets a default value of "Unknown" for books without genres.
    response = select(book.title, book.genres.or_("Unknown"))

print(response.results)

See the documentation for .add() and .extend() for further details on multi-valued properties.

See Also#