Skip to content

type_bridge.crud.has_lookup

has_lookup

Cross-type and narrowed attribute lookup.

Provides :func:has_lookup which builds and executes a TypeQL query that finds all entity or relation instances owning a given attribute, optionally filtered by value or expression and optionally narrowed to a concrete (or abstract base) type.

Two query shapes are emitted depending on whether type_name is set:

Cross-type form (type_name=None)::

# All entities with Name = "Alice"
match entity $e; $x isa $e, has Name "Alice";
fetch { "_iid": iid($x), "_type": label($e), "attributes": { $x.* } };

# All relations with Name attribute (any value)
match relation $r; $x isa $r, has Name $n;
fetch { "_iid": iid($x), "_type": label($r), "attributes": { $x.* } };

Narrowed form (type_name="some_type")::

# All instances of some_type (and its subtypes) with Name = "Alice".
# Uses isa! + sub so that label($t) recovers the concrete subtype.
# `label($x)` is illegal because $x is an Object variable.
match $t sub some_type; $x isa! $t, has Name "Alice";
fetch { "_iid": iid($x), "_type": label($t), "attributes": { $x.* } };

Hydration:

  • Entity results are hydrated from the wildcard $x.* payload directly (single query, no follow-up).
  • Relation results are re-fetched via concrete_class.manager(connection).get(_iid=iid) so that role players are populated. The relation hydration path is therefore N+1 in the number of returned relations; this is accepted because relation result sets from attribute lookups are typically small.

has_lookup

has_lookup(connection, attr_class, value=None, *, kind, type_name=None)

Find all instances of kind that own attr_class, with optional filter.

Parameters:

Name Type Description Default
connection Connection

Database, Transaction, or TransactionContext.

required
attr_class type[Attribute]

The attribute type to search for (e.g. Name).

required
value Any | None

Optional filter — may be: - None → return all instances that own the attribute - A raw Python value or :class:Attribute instance → exact match - An :class:Expression (e.g. Name.gt(Name("B"))) → comparison

None
kind Literal['entity', 'relation']

"entity" or "relation" — selects the TypeDB kind keyword.

required
type_name str | None

Optional concrete TypeDB type name to narrow the match to. When set, results are restricted to that type and its subtypes.

None

Returns:

Type Description
list[TypeDBType]

Hydrated model instances (mixed concrete types).

Source code in type_bridge/crud/has_lookup.py
def has_lookup(
    connection: Connection,
    attr_class: type[Attribute],
    value: Any | None = None,
    *,
    kind: Literal["entity", "relation"],
    type_name: str | None = None,
) -> list[TypeDBType]:
    """Find all instances of *kind* that own *attr_class*, with optional filter.

    Args:
        connection: Database, Transaction, or TransactionContext.
        attr_class: The attribute type to search for (e.g. ``Name``).
        value: Optional filter — may be:
            - ``None``  → return all instances that own the attribute
            - A raw Python value or :class:`Attribute` instance → exact match
            - An :class:`Expression` (e.g. ``Name.gt(Name("B"))``) → comparison
        kind: ``"entity"`` or ``"relation"`` — selects the TypeDB kind keyword.
        type_name: Optional concrete TypeDB type name to narrow the match to.
            When set, results are restricted to that type and its subtypes.

    Returns:
        Hydrated model instances (mixed concrete types).
    """
    from type_bridge.models.registry import ModelRegistry
    from type_bridge.session import ConnectionExecutor

    query = _build_has_query(attr_class, value, kind=kind, type_name=type_name)

    # Execute
    from typedb.driver import TransactionType

    executor = ConnectionExecutor(connection)
    results = executor.execute(query, TransactionType.READ)

    # Hydrate (relations route through manager.get to recover role players)
    return _hydrate_results(results, ModelRegistry, connection=connection)