--- id: 124 state: approved created: 2020-03-20 placement: category: resource-design order: 40 --- # Resource association APIs sometimes have resource hierarchies that can not be cleanly expressed in the usual tree structure. For example, a resource may have a many-to-one relationship with two other resource types instead of just one. Alternatively, a resource may have a many-to-many relationship with another resource type. ## Guidance A resource **must** have at most one canonical parent, and `List` requests **must not** require two distinct "parents" to work. ### Multiple many-to-one associations If a resource has a many-to-one relationship with multiple resource types, it **must** choose at most one of them to be the canonical parent. The resource **may** be associated with other resources through other fields on the resource. ```proto message Book { // The resource name pattern for Book indicates that Publisher is the // canonical parent. option (google.api.resource) = { type: "library.googleapis.com/Book" pattern: "publishers/{publisher}/books/{book}" }; // The resource name for the book. string name = 1 [(google.api.field_behavior) = IDENTIFIER]; // The resource name for the book's author. string author = 2 [(google.api.resource_reference) = { type: "library.googleapis.com/Author" }]; } ``` When listing resources with multiple associations in this way, the RPC **must** treat the `string parent` field as required as discussed in [AIP-132][], and **must not** add additional required arguments. The RPC **should** include a `string filter` field that allows users to filter by other resource associations as discussed in [AIP-160][]. **Note:** Resource reference fields **must** accept the same resource name format that is used in the `name` field of the referenced resource. ### Many-to-many associations Many-to-many associations are less common in APIs than they are in relational databases, in part because they are more difficult to model and present over network interfaces. An API **may** contain many-to-many relationships, and **should** use a repeated field containing a list of resource names, following the principles described for repeated fields in [AIP-144][]. ```proto message Book { option (google.api.resource) = { type: "library.googleapis.com/Book" pattern: "publishers/{publisher}/books/{book}" }; string name = 1 [(google.api.field_behavior) = IDENTIFIER]; // The resource names for the book's authors. repeated string authors = 2 [(google.api.resource_reference) = { type: "library.googleapis.com/Author" }]; } ``` **Note:** See [AIP-144][] for more information on repeated fields, including how to handle common issues such as atomic changes. If the use of a repeated field is too restrictive, or if more metadata is required along with the association, an API **may** model a many-to-many relationship using a sub-resource with two one-to-many associations. ```proto message BookAuthor { // The resource pattern for BookAuthor indicates that Book is the // canonical parent. option (google.api.resource) = { type: "library.googleapis.com/BookAuthor" pattern: "publishers/{publisher}/books/{book}/authors/{book_author}" }; // The resource name for the book-author association. string name = 1 [(google.api.field_behavior) = IDENTIFIER]; // The resource name for the author. string author = 2 [(google.api.resource_reference) = { type: "library.googleapis.com/Author" }]; // Other fields... } ``` **Note:** Using subresources to model an association between resources is only recommended if additional metadata is required in the relationship, or if the restrictions around the use of a repeated field preclude the use of that approach. [aip-132]: ./0132.md [aip-144]: ./0144.md [aip-160]: ./0160.md ## Changelog - **2021-04-07**: Clarified that resource reference fields accept resource names with the same format as the `name` field of the resource.