> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/pocketbase/pocketbase/llms.txt
> Use this file to discover all available pages before exploring further.

# Relation field

> Store references to records from other collections

The relation field stores references to records in other collections. It supports both single and multiple record references, with validation to ensure referenced records exist.

## Configuration options

<ParamField path="collectionId" type="string" required>
  The ID of the related collection. This cannot be changed after the field is created.
</ParamField>

<ParamField path="cascadeDelete" type="bool" default="false">
  When true, deletes the current record if all its linked relations are deleted.
</ParamField>

<ParamField path="minSelect" type="int" default="0">
  Minimum number of required relation records. Set to 0 for no minimum limit.
</ParamField>

<ParamField path="maxSelect" type="int" default="1">
  Maximum number of relation records that can be linked. Set to 1 (or less) for single relation mode. Set to > 1 for multiple relations mode.
</ParamField>

<ParamField path="required" type="bool" default="false">
  When true, requires at least one relation to be set.
</ParamField>

## Validation rules

The relation field validates:

* **Collection exists**: Referenced collection must exist and be accessible
* **Records exist**: All referenced record IDs must exist in the related collection
* **Min select**: If set, minimum number of relations must be met
* **Max select**: Number of relations cannot exceed the maximum
* **Required**: If enabled, at least one relation must be set

<Warning>
  The `collectionId` cannot be changed after the field is created to prevent breaking existing data relationships.
</Warning>

## Single vs multiple relations

<Info>
  The field behavior changes based on `maxSelect`:

  * `maxSelect <= 1`: Single relation mode (value is a record ID string)
  * `maxSelect > 1`: Multiple relations mode (value is an array of record IDs)
</Info>

## Special setter modifiers

The relation field supports modifiers for manipulating relations:

<CodeGroup>
  ```go Append relations theme={null}
  // Add relations to the end
  record.Set("categories+", []string{"id1", "id2"})
  // Before: ["oldId1", "oldId2"]
  // After:  ["oldId1", "oldId2", "id1", "id2"]
  ```

  ```go Prepend relations theme={null}
  // Add relations to the beginning
  record.Set("+categories", []string{"id1", "id2"})
  // Before: ["oldId1", "oldId2"]
  // After:  ["id1", "id2", "oldId1", "oldId2"]
  ```

  ```go Remove relations theme={null}
  // Remove specific relations
  record.Set("categories-", "oldId1")
  // Before: ["oldId1", "oldId2", "id3"]
  // After:  ["oldId2", "id3"]
  ```
</CodeGroup>

## Go examples

<Tabs>
  <Tab title="Single relation">
    ```go theme={null}
    import "github.com/pocketbase/pocketbase/core"

    field := &core.RelationField{
        Name:         "author",
        Required:     true,
        MaxSelect:    1,
        CollectionId: "users_collection_id",
    }

    collection.Fields.Add(field)

    // Set single relation
    record.Set("author", "user_record_id")
    ```
  </Tab>

  <Tab title="Multiple relations">
    ```go theme={null}
    field := &core.RelationField{
        Name:         "categories",
        Required:     false,
        MaxSelect:    5,
        CollectionId: "categories_collection_id",
    }

    collection.Fields.Add(field)

    // Set multiple relations
    record.Set("categories", []string{
        "category_id_1",
        "category_id_2",
        "category_id_3",
    })
    ```
  </Tab>

  <Tab title="With min/max constraints">
    ```go theme={null}
    field := &core.RelationField{
        Name:         "tags",
        Required:     true,
        MinSelect:    1,
        MaxSelect:    10,
        CollectionId: "tags_collection_id",
    }

    collection.Fields.Add(field)

    // Must have at least 1, max 10 tags
    record.Set("tags", []string{"tag1", "tag2", "tag3"})
    ```
  </Tab>

  <Tab title="With cascade delete">
    ```go theme={null}
    field := &core.RelationField{
        Name:          "project",
        Required:      true,
        MaxSelect:     1,
        CollectionId:  "projects_collection_id",
        CascadeDelete: true, // Delete task when project is deleted
    }

    collection.Fields.Add(field)

    record.Set("project", "project_id")
    ```
  </Tab>
</Tabs>

## Database column type

The column type varies based on whether it's single or multiple relations:

<CodeGroup>
  ```sql Single relation (maxSelect <= 1) theme={null}
  TEXT DEFAULT '' NOT NULL
  ```

  ```sql Multiple relations (maxSelect > 1) theme={null}
  JSON DEFAULT '[]' NOT NULL
  ```
</CodeGroup>

## Common patterns

<CodeGroup>
  ```go One-to-many (author -> articles) theme={null}
  // In articles collection
  field := &core.RelationField{
      Name:         "author",
      Required:     true,
      MaxSelect:    1,
      CollectionId: "users",
  }
  ```

  ```go Many-to-many (articles <-> tags) theme={null}
  // In articles collection
  field := &core.RelationField{
      Name:         "tags",
      MaxSelect:    20,
      CollectionId: "tags",
  }
  ```

  ```go Self-referencing (parent category) theme={null}
  field := &core.RelationField{
      Name:         "parent",
      MaxSelect:    1,
      CollectionId: "categories", // Same collection
  }
  ```

  ```go Required with minimum theme={null}
  field := &core.RelationField{
      Name:         "reviewers",
      Required:     true,
      MinSelect:    2, // At least 2 reviewers required
      MaxSelect:    5,
      CollectionId: "users",
  }
  ```
</CodeGroup>

## Expand relations in API

When querying records with relations, use the `expand` parameter to include related record data:

<CodeGroup>
  ```javascript Single relation expand theme={null}
  const record = await pb.collection('articles').getOne('RECORD_ID', {
      expand: 'author'
  });

  // Access expanded author
  console.log(record.expand.author.name);
  ```

  ```javascript Multiple relations expand theme={null}
  const record = await pb.collection('articles').getOne('RECORD_ID', {
      expand: 'categories,tags'
  });

  // Access expanded arrays
  record.expand.categories.forEach(cat => {
      console.log(cat.name);
  });
  ```
</CodeGroup>

## View collection restrictions

<Warning>
  Only view collections can have relations to other view collections. Regular collections cannot reference view collections.
</Warning>

## Best practices

<Note>
  * Use descriptive relation field names that indicate the relationship (e.g., `author`, `categories`, `assignedTo`)
  * Set appropriate `minSelect` and `maxSelect` constraints for data integrity
  * Use `cascadeDelete` carefully as it can lead to unintended data loss
  * Consider indexing relation fields for better query performance
  * Use the `expand` parameter when fetching records to avoid N+1 queries
  * Remember that changing `collectionId` is not allowed after creation
</Note>

## Zero value

* **Single relation**: Empty string `""`
* **Multiple relations**: Empty array `[]`
