TypeDB.Concept (TypeDB v0.9.0)

Copy Markdown View Source

The concepts TypeDB returns inside conceptRows answers.

Every entry in a row is one of:

StructTypeQLNotes
TypeDB.Concept.Entityan entity instanceiid, optional type
TypeDB.Concept.Relationa relation instanceiid, optional type
TypeDB.Concept.Attributean attribute instanceiid, value, value_type, optional type
TypeDB.Concept.Valuea computed valuevalue, value_type
TypeDB.Concept.EntityTypeentity typelabel
TypeDB.Concept.RelationTyperelation typelabel
TypeDB.Concept.AttributeTypeattribute typelabel, optional value_type
TypeDB.Concept.RoleTypea relation rolelabel
nilan unbound optional variable
a lista list-valued variableelements are concepts

type is nil when the query ran with include_instance_types: false.

Values

value holds the value exactly as it came over the wire, which is what the HTTP API defines: JSON primitives for boolean, integer, double and string, and strings for decimal, date, datetime, datetime-tz and duration.

Use typed_value/1 to convert to native Elixir terms:

iex> attr = %TypeDB.Concept.Attribute{iid: "0x1", value: "2024-03-01", value_type: "date"}
iex> TypeDB.Concept.typed_value(attr)
~D[2024-03-01]

Conversion never loses information: datetime-tz and duration become TypeDB.DateTimeTZ and TypeDB.Duration structs, which keep the original wire form alongside the parsed fields.

Summary

Types

What kind of thing a concept is, in one atom.

A row entry: a concept, an unbound variable, or a list of concepts.

t()

Functions

Casts a wire value given its TypeDB value type name.

What kind of thing a concept is.

Decodes one wire-format row entry into concept structs.

Returns the iid of an instance, or nil for types and values.

Whether the concept is data rather than schema.

Returns the label of a type, or of the type of an instance when it was included.

Whether the concept is a type.

Returns the value converted to a native Elixir term.

Returns the wire-format value of an attribute or value concept, nil otherwise.

Whether the concept is a bare value — a computed one, belonging to no instance.

Types

category()

@type category() ::
  :entity
  | :relation
  | :attribute
  | :entity_type
  | :relation_type
  | :attribute_type
  | :role_type
  | :value

What kind of thing a concept is, in one atom.

The same eight the protocol distinguishes, spelled the way Elixir spells atoms — :entity_type, not :entityType.

entry()

@type entry() :: t() | nil | [t()]

A row entry: a concept, an unbound variable, or a list of concepts.

instance()

t()

@type t() :: instance() | type() | TypeDB.Concept.Value.t()

type()

Functions

cast(value, arg2)

@spec cast(term(), String.t()) :: term()

Casts a wire value given its TypeDB value type name.

category(arg1)

@spec category(t()) :: category()

What kind of thing a concept is.

The counterpart of Rust's Concept::get_category, and the reason it is worth having in a language with pattern matching: a case on this is one line per branch, where matching the structs means knowing all eight module names.

iex> TypeDB.Concept.category(%TypeDB.Concept.Entity{iid: "0x0", type: nil})
:entity

iex> TypeDB.Concept.category(%TypeDB.Concept.AttributeType{label: "name"})
:attribute_type

Rust's other thirty-odd accessors are deliberately not here. try_get_integer and its dozen siblings say in a method what typed_value/1 says once, and is_entity is match?(%Entity{}, concept) — a predicate that reads worse than the match it wraps. What survives the translation is this, plus the three predicates below, which answer questions the struct name alone does not.

decode(entries)

@spec decode(term()) :: entry()

Decodes one wire-format row entry into concept structs.

Raises TypeDB.Error with kind: :decode when the payload does not look like anything the HTTP API can produce.

iid(arg1)

@spec iid(t()) :: String.t() | nil

Returns the iid of an instance, or nil for types and values.

instance?(concept)

@spec instance?(t()) :: boolean()

Whether the concept is data rather than schema.

iex> TypeDB.Concept.instance?(%TypeDB.Concept.Entity{iid: "0x0", type: nil})
true

iex> TypeDB.Concept.instance?(%TypeDB.Concept.EntityType{label: "person"})
false

label(arg1)

@spec label(t()) :: String.t() | nil

Returns the label of a type, or of the type of an instance when it was included.

type?(concept)

@spec type?(t()) :: boolean()

Whether the concept is a type.

iex> TypeDB.Concept.type?(%TypeDB.Concept.RoleType{label: "friendship:friend"})
true

typed_value(arg1)

@spec typed_value(t()) :: term()

Returns the value converted to a native Elixir term.

  • booleanboolean
  • integerinteger
  • doublefloat
  • stringString.t()
  • decimalDecimal.t() when the optional Decimal library is loaded, otherwise a string. TypeDB renders decimals with TypeQL's literal suffix ("12.345dec"), which is stripped either way — the value differs in type when Decimal is absent, not in content. The suffix survives in TypeDB.Concept.value/1, which is the raw wire value
  • dateDate.t()
  • datetimeNaiveDateTime.t()
  • datetime-tzTypeDB.DateTimeTZ.t()
  • durationTypeDB.Duration.t()

Values that cannot be parsed are returned unchanged rather than raising, so a future TypeDB value type never breaks a running application.

value(arg1)

@spec value(t()) :: term()

Returns the wire-format value of an attribute or value concept, nil otherwise.

value?(concept)

@spec value?(t()) :: boolean()

Whether the concept is a bare value — a computed one, belonging to no instance.

iex> TypeDB.Concept.value?(%TypeDB.Concept.Value{value: 3, value_type: "integer"})
true

An attribute is not one: it has a value and is also a thing in the database. value/1 and typed_value/1 read both.