Edges
#
Quick SummaryEdges are the relations (or associations) of entities. For example, user's pets, or group's users.
In the example above, you can see 2 relations declared using edges. Let's go over them.
1. pets
/ owner
edges; user's pets and pet's owner -
ent/schema/user.go
ent/schema/pet.go
As you can see, a User
entity can have many pets, but a Pet
entity can have only one owner.
In relationship definition, the pets
edge is a O2M (one-to-many) relationship, and the owner
edge
is a M2O (many-to-one) relationship.
The User
schema owns the pets/owner
relationship because it uses edge.To
, and the Pet
schema
just has a back-reference to it, declared using edge.From
with the Ref
method.
The Ref
method describes which edge of the User
schema we're referencing because there can be multiple
references from one schema to other.
The cardinality of the edge/relationship can be controlled using the Unique
method, and it's explained
more widely below.
2. users
/ groups
edges; group's users and user's groups -
ent/schema/group.go
ent/schema/user.go
As you can see, a Group entity can have many users, and a User entity can have have many groups.
In relationship definition, the users
edge is a M2M (many-to-many) relationship, and the groups
edge is also a M2M (many-to-many) relationship.
#
To and Fromedge.To
and edge.From
are the 2 builders for creating edges/relations.
A schema that defines an edge using the edge.To
builder owns the relation,
unlike using the edge.From
builder that gives only a back-reference for the relation (with a different name).
Let's go over a few examples that show how to define different relation types using edges.
#
Relationship- O2O Two Types
- O2O Same Type
- O2O Bidirectional
- O2M Two Types
- O2M Same Type
- M2M Two Types
- M2M Same Type
- M2M Bidirectional
#
O2O Two TypesIn this example, a user has only one credit-card, and a card has only one owner.
The User
schema defines an edge.To
card named card
, and the Card
schema
defines a back-reference to this edge using edge.From
named owner
.
ent/schema/user.go
ent/schema/card.go
The API for interacting with these edges is as follows:
The full example exists in GitHub.
#
O2O Same TypeIn this linked-list example, we have a recursive relation named next
/prev
. Each node in the list can
have only one next
node. If a node A points (using next
) to node B, B can get its pointer using prev
(the back-reference edge).
ent/schema/node.go
As you can see, in cases of relations of the same type, you can declare the edge and its reference in the same builder.
The API for interacting with these edges is as follows:
The full example exists in GitHub.
#
O2O BidirectionalIn this user-spouse example, we have a symmetric O2O relation named spouse
. Each user can have only one spouse.
If user A sets its spouse (using spouse
) to B, B can get its spouse using the spouse
edge.
Note that there are no owner/inverse terms in cases of bidirectional edges.
ent/schema/user.go
The API for interacting with this edge is as follows:
The full example exists in GitHub.
#
O2M Two TypesIn this user-pets example, we have a O2M relation between user and its pets.
Each user has many pets, and a pet has one owner.
If user A adds a pet B using the pets
edge, B can get its owner using the owner
edge (the back-reference edge).
Note that this relation is also a M2O (many-to-one) from the point of view of the Pet
schema.
ent/schema/user.go
ent/schema/pet.go
The API for interacting with these edges is as follows:
The full example exists in GitHub.
#
O2M Same TypeIn this example, we have a recursive O2M relation between tree's nodes and their children (or their parent).
Each node in the tree has many children, and has one parent. If node A adds B to its children,
B can get its owner using the owner
edge.
ent/schema/node.go
As you can see, in cases of relations of the same type, you can declare the edge and its reference in the same builder.
The API for interacting with these edges is as follows:
The full example exists in GitHub.
#
M2M Two TypesIn this groups-users example, we have a M2M relation between groups and their users. Each group has many users, and each user can be joined to many groups.
ent/schema/group.go
ent/schema/user.go
The API for interacting with these edges is as follows:
The full example exists in GitHub.
#
M2M Same TypeIn this following-followers example, we have a M2M relation between users to their followers. Each user can follow many users, and can have many followers.
ent/schema/user.go
As you can see, in cases of relations of the same type, you can declare the edge and its reference in the same builder.
The API for interacting with these edges is as follows:
The full example exists in GitHub.
#
M2M BidirectionalIn this user-friends example, we have a symmetric M2M relation named friends
.
Each user can have many friends. If user A becomes a friend of B, B is also a friend of A.
Note that there are no owner/inverse terms in cases of bidirectional edges.
ent/schema/user.go
The API for interacting with these edges is as follows:
The full example exists in GitHub.
#
Edge FieldThe Field
option for edges allows users to expose foreign-keys as regular fields on the schema.
Note that only relations that hold foreign-keys (edge-ids) are allowed to use this option.
The API for interacting with edge-fields is as follows:
Multiple examples exists in GitHub.
#
Migration To Edge FieldsAs mentioned in the StorageKey section, Ent configures edge storage-keys (e.g. foreign-keys) by the
edge.To
. Therefore, if you want to add a field to an existing edge (already exists in the database as a column),
you need to set it up with the StorageKey
option as follows:
Alternatively, this option can be configured on the edge-field instead:
If you're not sure how the foreign-key was named before using the edge-field option,
check out the generated schema description in your project: <project>/ent/migrate/schema.go
.
#
RequiredEdges can be defined as required in the entity creation using the Required
method on the builder.
If the example above, a card entity cannot be created without its owner.
#
StorageKeyBy default, Ent configures edge storage-keys by the edge-owner (the schema that holds the edge.To
), and not the by
back-reference (edge.From
). This is because back-references are optional and can be removed.
In order to use custom storage configuration for edges, use the StorageKey
method as follows:
#
Struct TagsCustom struct tags can be added to the generated entities using the StructTag
method. Note that if this option was not provided, or provided and did not
contain the json
tag, the default json
tag will be added with the field name.
#
IndexesIndexes can be defined on multi fields and some types of edges as well. However, you should note, that this is currently an SQL-only feature.
Read more about this in the Indexes section.
#
AnnotationsAnnotations
is used to attach arbitrary metadata to the edge object in code generation.
Template extensions can retrieve this metadata and use it inside their templates.
Note that the metadata object must be serializable to a JSON raw value (e.g. struct, map or slice).
Read more about annotations and their usage in templates in the template doc.
#
Naming ConventionBy convention edge names should use snake_case
. The corresponding struct fields generated by ent
will follow the Go convention
of using PascalCase
. In cases where PascalCase
is desired, you can do so with the StorageKey
or StructTag
methods.