Overview
A relationship is a connection between two documents. Relationships allow you to reference and query related documents in read and write operations, even if the documents are in separate databases or collections.
You define a relationship on a source MongoDB collection and link to documents in a foreign collection. Atlas App Services automatically resolves relationships in synced SDK data models by replacing the values in a source field with the foreign documents that they reference.
Relationships are unidirectional and don't enforce uniqueness or other foreign key constraints. If you reference a non-existent foreign value in a source field, App Services automatically omits the reference from resolved relationships.
Example
Consider an application that has two collections:
The
accountscollection contains documents that each describe a customer account.Account Collection Schema{ "title": "Account", "properties": { "_id": { "bsonType": "objectId" }, "account_id": { "bsonType": "string" }, "products": { "bsonType": "array", "items": { "bsonType": "string" } }, ... } } The
customerscollection contains documents that each describe a single customer that can have one or more accounts. Every document in thecustomerscollection has anaccountsfield that contains an array of everyaccount_idvalue from theaccountscollection that applies to the customer.Customer Collection Schema{ "title": "Customer", "properties": { "username": { "bsonType": "string" }, "accounts": { "bsonType": "array", "items": { "bsonType": "string" } }, ... } }
The app defines this relationship on the customers collection. It
points from the array of account id values stored in the accounts
field to the account_id field of each document in the
accounts collection.
{ "accounts": { "ref": "#/relationship/mongodb-atlas/sample_analytics/accounts", "foreign_key": "account_id", "is_list": true } }
With this relationship defined, App Services can return a customer and all
of their accounts in client queries. Without a relationship,
the queries would return a list of just account_id values instead
of the full Account objects.
Cardinality
A relationship's cardinality determines the number of foreign documents that it can reference. App Services supports two relationship cardinalities: "to-one" and "to-many".
To-One
A to-one relationship links each source document with either a single document or an array of documents from the foreign collection.
To indicate that a relationship has "to-one" cardinality, set
is_list to false:
{ "owner": { "ref": "#/relationship/mongodb-atlas/example/people", "foreign_key": "_id", "is_list": false } }
App Services automatically replaces source values with the referenced objects or a null value in SDK models:
{ "name": "Pet", "properties": { "name": "string", "owner": "Person" } } { "name": "Person", "properties": { "name": "string" } }
To-Many
A to-many relationship links each source document with a list of documents from the foreign collection.
To indicate that a relationship has "to-many" cardinality, set
is_list to true:
{ "pets": { "ref": "#/relationship/mongodb-atlas/example/pets", "foreign_key": "_id", "is_list": true } }
App Services automatically replaces source values with the referenced objects or a null value in SDK models:
{ "name": "Pet", "properties": { "name": "string" } } { "name": "Person", "properties": { "name": "string", "pets": "Pet[]" } }
Embedded Object Relationships
Embedded Objects can have relationships with foreign collections. Use dot notation to access properties in embedded objects.
Embedded Object to Another Collection
An embedded object can have a relationship with an object in a foreign collection.
{ "title": "Person", "properties": { "_id": { "bsonType": "objectId" }, "pet": { "bsonType":"object", "properties": { "favoriteToyBrand": { "bsonType": "objectId" } } } // ...additional model properties } }
Use dot notation to specify the embedded object property that has a relationship with the foreign collection. Then, you can specify the foreign collection details and foreign key field.
{ "pet.favoriteToyBrand": { "ref": "#/relationship/mongodb-atlas/example/ToyBrand", "foreign_key": "_id", "is_list": false } }
Embedded Object Within a List
An embedded object that is within a list property can have a relationship with a foreign collection.
{ "title": "Person", "properties": { "_id": { "bsonType": "objectId" }, "pets": { "bsonType":"array", "items": { "bsonType": "object", "properties": { "favoriteToyBrand": { "bsonType": "objectId" } } } } // ...additional model properties } }
To access an embedded object property contained in a list, use
field1.[].field2 (for example, pets.[].favoriteToyBrand). From there,
you can specify the foreign collection details and foreign key field.
Tip
Use the same syntax with dictionaries and sets
You can use this same field1.[].field2 syntax when creating relationships
within dictionaries and sets.
{ "pets.[].favoriteToyBrand": { "ref": "#/relationship/mongodb-atlas/example/ToyBrand", "foreign_key": "_id", "is_list": false } }
Note
Primitives versus lists, dictionaries, and sets in relationships
In the example above, is_list is set to false. The field at the end
of the relationship string here is a primitive, not a list. The embedded
object is contained in a list, but the favoriteToyBrand property
itself is not a dictionary, set, or list.
Define a Relationship
When you define a relationship, keep these limitations in mind:
The reference (source) field cannot be
_id.The reference (source) field cannot be a
requiredfield.If you are using Device Sync, the foreign key must be the
_idfield of the foreign collection.
Define Schemas
To define a relationship, you must have a schema defined for both the source collection and the foreign collection. To learn how to define schemas, see Define & Enforce a Schema.
Create a New Relationship
You define a relationship for collections in a linked MongoDB data source alongside the schema.
To create a new relationship:
Click Schema in the left navigation menu.
From the Collections tab, select the source collection.
Toggle the View to JSON View, and click + Add Relationship.
To create a new relationship, add a relationship configuration
object to the source collection's relationships.json file:
{ "<source field>": { "ref": "#/relationship/<data source>/<db>/<collection>", "foreign_key": "<foreign field>", "is_list": <boolean> } }
Configure the Relationship
A relationship definition maps from a reference field in the source collection's schema to a foreign field of the same type in the foreign collection's schema.
To configure the relationship:
Specify the field in the source collection that the relationship maps from. This is referred to as the parent in the UI.
Specify the foreign database, collection, and field in the foreign collection to map to the source field. These are referred to as linked in the UI. If you are using Device Sync, the linked field must be
_id.Click Add.
To configure the relationship, specify the source field name as a
root-level field in relationships.json, then add the
following configuration options in the field's value:
Specify the foreign collection in the
reffield using the following format:#/relationship/<data source>/<db>/<collection> Specify the field to match in the
foreign_keyfield. If you are using Device Synce, this must be_id.If the source field contains an array, set
is_listtotrue, otherwise set it tofalse.