Adding constraints and rules

In addition to the basic cardinality constraints for slots, additional constraints can be specified

Unique Key

A class can declare unique_keys, a set of slots that are unique for members of that class.

For example, a database of chemical entities may with to declare the tuple of atomic number and neutron number as a unique key for an isotope:

  ChemicalEntity:
    slots:
      - id
      - symbol
      - inchi
      - atomic_number
      - neutron_number
  ChemicalElement:
    is_a: ChemicalEntity

  Isotope:
    is_a: ChemicalEntity
    unique_keys:
      main:
        description: An isotope is uniquely identifier by atomic and neutron number
        unique_key_slots:
          - atomic_number
          - neutron_number
      symbol:
        description: An isotope is uniquely identifier by its symbol
        notes:
          - we could have opted to use a simple key slot here as this is not a compound key but this allows us to annotate the key
        unique_key_slots:
          - symbol

identifiers are special cases of unique keys.

String serialization

A rule for generating the string value of a slot can be specified as a string_serialization

classes:
  Person:
    attributes:
      first:
      last:
      full:
        string_serialization: "{first} {last}"
  • Tools for performing missing value inference can then populate the full slot based on the other two slots

  • Tools for performing validation can use this to check slot values

    • if all 3 slots are populated, missing value inference can be used to check for consistency

    • if only full is provided, then the string can be checked (e.g. by a regex) to ensure the syntax is consistent

See:

Patterns

The value of a slot can be constrained to conform to a particular string pattern using the pattern metaslot

Example:

  slots:
     phone:
       pattern: "^[\\d\\(\\)\\-]+$"   ## regular expression

See:

Structured patterns

The structured_pattern construct allows you to provide patterns in a more structured way, and to reuse sub-patterns.

First you declare the patterns to be reused in the top level of your schema:

settings:
  float: "\\d+[\\.\\d+]"
  unit: "\\S+"
  email: "\\S+@\\S+{\\.\\w}+"

You can then use this inside a structured pattern:

  height:
    range: string
    structured_pattern:
      syntax: "{float} {unit.length}"
      interpolated: true
      partial_match: false

You can use gen-linkml to expand these into structured patterns

Minimum and Maximum values

Any numeric value can have minimum and maximum values specified

Expressions and other advanced features

The above describes the core constraint feature. See the advanced features guide for more on how to write rules and expressions for more expressive constraints.