title | description |
---|---|
Has One |
Define one-to-one relationships between feature classes. |
import { PyDiffEditor } from '@/components/Editor' import { highlightedCode as oneToOneDiff } from '@/samples/features/one_to_one.py?highlight=diff-py' import { highlightedCode as hasOneOptionalDiff } from '@/samples/features/one_to_one_optional.py?highlight=diff-py' import { TipInfo } from '@/components/Tip'
Has-one relationships link a feature to a single instance of another feature.
The simplest way to specify a join for a has-one relationship is implicitly. In the example below,
a User
is linked to their Profile
.
from chalk.features import features
@features
class Profile:
id: str
user_id: "User.id"
email_age_years: float
@features
class User:
id: str
profile: Profile
With a has-one relationship established, you can reference features on Profile
through
User
. For example:
user_email_age = User.profile.email_age_years
In the following snippet, the has-one join is explicitly defined. This is functionally equivalent to the recommended implementation:
from chalk.features import features, has_one, ...
@features
class Profile:
id: str
user_id: str
email_age_years: float
@features
class User:
id: str
uid: str
profile: Profile = has_one(lambda: Profile.user_id == User.uid)
lambda
solves forward references, letting you reference User
before it is defined.
You can also add a back-reference to User
from Profile
.
However, you don't have to explicitly set the join on Profile
.
Instead, the join condition is assumed to be symmetric and copied over.
To complete the one-to-one relationship from our example, add a User
to the Profile
class:
Here you need to use quotes around User
to use a forward reference.
When a has-one relationship is specified, the default behavior is to treat the linked Feature
as required. Following the example above, specifying a User
without a Profile
and
querying for a User
's profile or using the User.profile
in a resolver raises an
error.
To define optional relationships, use the typing.Optional[...]
keyword:
Note, resolvers that take optional features as inputs need to handle the None
case. This is
covered in more detail in the resolver's section of the docs.