# Relations

Records from different collections can be related to each other. There are two kinds of relations between collections:

* **One to many.** If one record from collection **A** can be linked with many ones in collection **B**, but any of records from **B** can be linked only with single record from **A**.
* **Many to many.** If any record from **A** can be linked with unlimited number of records from collection **B** and any **B** record also can be linked with many records from **A** too.&#x20;

{% embed url="<https://www.youtube.com/watch?v=Awx4u7M9nbc&list=PLh0rZ0-uVht6uD-_iVv58GR45kDBXrgw3&index=9&t=0s>" %}

Tabbli uses record keys for storing relations inside the database. So, if you work with relations inside templates you can use keys for making requests for fetching additional data. For example, we have some student with relations to particular classes.

![](/files/-LtyublC2TJHm_DmlkuL)

You can use the next operator for fetch a record data with particular key:

```python
{% set record = DB().get_collection("students").get_record(key="student-angel-henry").get_dict() %}
```

The content of `record` variable here will be like that:

```python
{'attached_images': [{'image': 'images/records/6fb96848-7a02-4f1f-8a1e-fa6010c55da1/69ad9b3f54594da19951c2ea683b73f4.png',
                      'name': {'en': 'Angel Henry'},
                      'url': 'https://demo.tabbli.com/media/images/records/6fb96848-7a02-4f1f-8a1e-fa6010c55da1/69ad9b3f54594da19951c2ea683b73f4.png'}],
 'children': {'count': 0},
 'filtered_properties': ['classes'],
 'id': '6fb96848-7a02-4f1f-8a1e-fa6010c55da1',
 'important_properties': ['bday', 'email', 'phone', 'classes'],
 'key': 'student-angel-henry',
 'language': 'en',
 'multilingual_properties': [],
 'name': {'en': 'Angel Henry'},
 'properties': {'bday': datetime.datetime(1991, 1, 6, 0, 0),
                'classes': [{'id': 'cd64970d-c395-43a4-bd8e-2c13dd95e38f',
                             'key': 'class-vessel-planing-with-tabbli',
                             'name': {'en': 'Vessel planing'}},
                            {'id': '6997cbb1-ba18-4ef4-adc0-67e1331e9271',
                             'key': 'class-project-logistics-courses',
                             'name': {'en': 'Equipment management'}},
                            {'id': '4c9fc47b-a780-42cc-a29a-2549fdd20479',
                             'key': 'class-english-at-the-morning',
                             'name': {'en': 'English at the Morning'}}],
                'email': 'john.gardner@example.com',
                'phone': '(252) 555-0126'},
 'property_names': {'bday': {'en': 'Date of birthday'},
                    'classes': {'en': 'Classes'},
                    'email': {'en': 'Email'},
                    'phone': {'en': 'Phone'}},
 'property_types': {'bday': 'date',
                    'classes': 'many_to_many',
                    'email': 'email',
                    'phone': 'string'},
 'record_subsets': [],
 'record_type': {'attached_images_support': True,
                 'children_support_children': False,
                 'key': 'student',
                 'name': {'en': 'Student'},
                 'nested_records_support': False}}
```

In that example the property with key `classes` represents a many-to-many relations to another collection "Class". In the structure above you can see that for each link is represented with its `id`, `key` and `name`.

```python
{
    'id': '4c9fc47b-a780-42cc-a29a-2549fdd20479',
    'key': 'class-english-at-the-morning',
    'name': {'en': 'English at the Morning'}
}
```

So, if you need extra information about related record you can use the proper operator again:

```python
{% set record_class = DB().get_collection("classes").get_record(key="class-english-at-the-morning").get_dict() %}
```

Result will be like that:

```python
{'attached_images': [],
 'children': {'count': 0},
 'filtered_properties': ['date', 'up_to', 'time', 'days'],
 'id': '4c9fc47b-a780-42cc-a29a-2549fdd20479',
 'important_properties': ['course', 'teacher', 'date', 'up_to', 'time', 'days'],
 'key': 'class-english-at-the-morning',
 'language': 'en',
 'multilingual_properties': [],
 'name': {'en': 'English at the Morning'},
 'properties': {'course': {'id': '533608ee-8d7c-4134-9b34-af7ecb203280',
                           'key': 'course-english-language',
                           'name': {'en': 'English Language'}},
                'date': datetime.datetime(2019, 11, 4, 0, 0),
                'days': 'Mon, Wed',
                'teacher': {'id': '71ddfe3c-8bc6-4491-ade6-5978f31675a3',
                            'key': 'person-brandon-howard',
                            'name': {'en': 'Brandon Howard'}},
                'time': '10:00 - 12:00',
                'up_to': datetime.datetime(2020, 5, 1, 0, 0)},
 'property_names': {'course': {'en': 'Course'},
                    'date': {'en': 'Date of starting'},
                    'days': {'en': 'Days of week'},
                    'teacher': {'en': 'Teacher'},
                    'time': {'en': 'Time'},
                    'up_to': {'en': 'Up to'}},
 'property_types': {'course': 'one_to_many',
                    'date': 'date',
                    'days': 'string',
                    'teacher': 'one_to_many',
                    'time': 'string',
                    'up_to': 'date'},
 'record_subsets': [],
 'record_type': {'attached_images_support': False,
                 'children_support_children': False,
                 'key': 'class',
                 'name': {'en': 'Class'},
                 'nested_records_support': False}}
```

In management interface you can see automatically created tabs for reverse relations:

![Reverse relations to another collection](/files/-LtyvpVjw5RzxuxZUVW1)

If you need to do the same in the code you can use filtering:

```python
{% set students_english_morning = DB().get_collection("students").get_filtered_records(filter_data={"f-classes": ["class-english-at-the-morning"]}).records %}
```

Despite regular collections Tabbli also supports a system structure **Users**. Because it is a system component, you cannot use the same principles for building relations like with other collections. For working with users, Tabbli supports the next property types:

* **User relation.** When a record could be linked with one user.
* **Multiple user relations.** When a record could be linked with multiple users.

As a key for relations with users Tabbli uses email. It also means, that email is required and unique property for users. You can also see reverse relations in the manahement interface on a user profile page.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://tabbli.gitbook.io/tabbli/working-with-data/relations.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
