Skip to content

not_

relationalai.semantics
not_(*args: Statement) -> Not

Return a negated condition for use in query filters.

This is a convenience wrapper around Model.not_ that operates on the single active model. You typically use not_ inside where to say “exclude anything that matches this pattern”. For example, not_(Person.pets) can be read as “people with no pets”.

If you pass multiple statements, they are treated as a single grouped condition and the whole group is negated. In other words, not_(a, b) means “NOT (a AND b)”, not “(NOT a) AND (NOT b)”. Note that NOT (a AND b) is equivalent to (NOT a) OR (NOT b).

If you have more than one model, call Model.not_ on the specific model instead.

  • Not - A negation expression.
  • relationalai.util.error.RAIException - If there is no active model, or if multiple models exist and the active model would be ambiguous.

Filter to people who have no pets:

>>> from relationalai.semantics import Model, String, define, where, not_
>>> m = Model()
>>> Person = m.Concept("Person")
>>> Pet = m.Concept("Pet")
>>> Person.pets = m.Relationship(f"{Person} has {Pet}")
>>> Pet.name = m.Property(f"{Pet} is named {String:name}")
>>> define(
... alice := Person.new(name="Alice"),
... bob := Person.new(name="Bob"),
... boots := Pet.new(name="boots"),
... bob.pets(boots),
... )
>>> where(Person, not_(Person.pets)).select(Person.name).to_df()

Exclude people who have a pet named “boots”:

>>> where(Person, not_(Person.pets.name == "boots")).select(Person.name).to_df()

Contrast grouped vs separate negation:

>>> # Grouped negation means NOT (A AND B). This excludes only people who
>>> # have a pet AND have a pet named "boots".
>>> where(Person, not_(Person.pets, Person.pets.name == "boots"))
>>> # Separate negation means (NOT A) AND (NOT B). This is stricter.
>>> # Here it keeps only people who have no pets (and therefore also do not
>>> # have a pet named "boots").
>>> where(Person, not_(Person.pets), not_(Person.pets.name == "boots"))