Over the past few months, there has been much discussion in the Ent project issues about adding support for the retrieval of the foreign key field when retrieving entities with One-to-One or One-to-Many edges. We are happy to announce that as of v0.7.0 ent supports this feature.
Prior to merging this branch, a user that wanted to retrieve the foreign-key field for an entity needed to use eager-loading. Suppose our schema looked like this:
The schema describes two related entities:
Pet, with a One-to-Many edge between them: a user can own many pets and a pet can have one owner.
When retrieving pets from the data storage, it is common for developers to want to access the foreign-key field on the pet. However, because this field is created implicitly from the
owner edge it was automatically accessible when retrieving an entity. To retrieve this from the storage a developer needed to do something like:
Aside from being very verbose, retrieving the pet with the owner this way was inefficient in-terms of database queries. If we execute the query with the
.Debug() we can see the DB queries ent generates to satisfy this call:
In this example, Ent first retrieves the Pet with an ID of
1, then redundantly fetches the
id field from the
users table for users with an ID of
Edge-field support greatly simplifies and improves the efficiency of this flow. With this feature, developers can define the foreign key field as part of the schemas
Fields(), and by using the
.Field(..) modifier on the edge definition instruct Ent to expose and map the foreign column to this field. So, in our example schema, we would modify it to be:
In order to update our client code we need to re-run code generation:
We can now modify our query to be much simpler:
Running with the
.Debug() modifier we can see that the DB queries make more sense now:
If you are already using Ent with an existing schema, you may already have O2M relations whose foreign-key columns already exist in your database. Depending on how you configured your schema, chances are that they may be stored in a column by a different name than the field you are now adding. For instance, you want to create an
owner_id field, but Ent auto-created the column foreign-key column as
To check what column name Ent is using for this field you can look in the
To allow for a smooth migration, you must explicitly tell Ent to keep using the existing column name. You can do this by using the
StorageKey modifier (either on the field or on the edge). For example:
In the near future we plan to implement Schema Versioning, which will store the history of schema changes alongside the code. Having this information will allow ent to support such migrations in an automatic and predictable way.
Edge-field support is readily available and can be installed by
go get -u firstname.lastname@example.org.
Many thanks 🙏 to all the good people who took the time to give feedback and helped design this feature properly: Alex Snast, Ruben de Vries, Marwan Sulaiman, Andy Day, Sebastian Fekete and Joe Harvey.