---
title: Children
---

Children define nested collections within a projection. Each child represents a collection of items that are managed independently but belong to a parent projection.

## Basic Syntax

```pdl
children {CollectionName} identified by {Identifier}
  {child blocks}
```

## Simple Example

```pdl
projection Group => GroupReadModel
  from GroupCreated
    Name = name

  children members identified by userId
    from UserAddedToGroup key userId
      parent groupId
      Name = userName
      Role = role
```

This creates a `members` collection where each member is identified by `userId`.

## Identifier Expression

The `identified by` specifies how to identify individual children:

```pdl
children orders identified by orderId
children members identified by userId
children items identified by itemNumber
```

## Parent Key

Use `parent` to specify the relationship to the parent projection:

```pdl
children members identified by userId
  from UserAddedToGroup key userId
    parent groupId
    Name = userName
```

The `parent groupId` links the child to the correct parent instance.

## With AutoMap

Apply AutoMap to children:

```pdl
children members identified by userId
  automap

  from UserAddedToGroup
    Role = role
```

## Multiple Events

Children can have multiple event types:

```pdl
children members identified by userId
  from UserAddedToGroup key userId
    parent groupId
    Name = userName
    Role = role

  from UserRoleChanged key userId
    parent groupId
    Role = role
```

## Every Block in Children

Apply mappings to all events within a children collection using the `every` block:

```pdl
children members identified by userId
  from UserAddedToGroup key userId
    parent groupId
    Role = role

  every
    Name = userName
    UpdatedAt = $eventContext.occurred
```

The `every` block within children works similarly to the top-level every block but applies only to events within that specific children collection. It's useful for mappings that should apply to all events affecting child items.

**Note:** The `exclude children` directive is not applicable within child every blocks as they already operate in a children context.

## Joins in Children

Children can have joins:

```pdl
children members id userId
  from UserAddedToGroup key userId
    parent groupId
    UserId = userId
    Role = role

  join User on UserId
    events UserCreated, UserUpdated
    Name = name
    Email = email
```

## Removal in Children

Remove children when specific events occur:

```pdl
children members id userId
  from UserAddedToGroup key userId
    parent groupId
    Role = role

  remove with UserRemovedFromGroup key userId
    parent groupId
```

See [Removal](/chronicle/projections/projection-declaration-language/removal/) for more details.

## Nested Children

Children can contain their own children:

```pdl
children departments id deptId
  from DepartmentCreated key deptId
    parent companyId
    Name = name

  children teams id teamId
    from TeamCreated key teamId
      parent deptId
      Name = name
```

## Examples

### Group Membership

```pdl
projection Group => GroupReadModel
  from GroupCreated
    Name = name
    Description = description

  children members id userId
    automap

    from UserAddedToGroup key userId
      parent groupId
      AddedAt = $eventContext.occurred

    from UserRoleChanged key userId
      parent groupId
      Role = role

    remove with UserRemovedFromGroup key userId
      parent groupId
```

### Order with Line Items

```pdl
projection Order => OrderReadModel
  from OrderPlaced
    OrderNumber = orderNumber
    CustomerId = customerId
    Total = 0

  children items id lineNumber
    from LineItemAdded key lineNumber
      parent orderId
      ProductId = productId
      Quantity = quantity
      UnitPrice = price
      LineTotal = total

    from LineItemQuantityChanged key lineNumber
      parent orderId
      Quantity = quantity
      LineTotal = total

    remove with LineItemRemoved key lineNumber
      parent orderId
```

### Project with Tasks

```pdl
projection Project => ProjectReadModel
  from ProjectCreated
    Name = name
    Status = "Active"

  children tasks id taskId
    every
      LastModified = $eventContext.occurred

    from TaskAdded key taskId
      parent projectId
      Title = title
      AssignedTo = assigneeId
      Status = "Open"
      CreatedAt = $eventContext.occurred

    from TaskCompleted key taskId
      parent projectId
      Status = "Completed"
      CompletedAt = $eventContext.occurred

    from TaskAssigned key taskId
      parent projectId
      AssignedTo = assigneeId

    join User on AssignedTo
      events UserCreated
      AssigneeName = name
```

### Invoice with Payments

```pdl
projection Invoice => InvoiceReadModel
  from InvoiceIssued
    InvoiceNumber = number
    CustomerId = customerId
    Amount = amount
    Balance = amount

  children payments id paymentId
    from PaymentReceived key paymentId
      parent invoiceNumber
      Amount = amount
      ReceivedAt = $eventContext.occurred
      Method = paymentMethod

  from PaymentReceived
    subtract Balance by amount
```

### Blog Post with Comments

```pdl
projection BlogPost => BlogPostReadModel
  from PostPublished
    Title = title
    Content = content
    AuthorId = authorId
    PublishedAt = $eventContext.occurred

  from PostUpdated
    Content = content
    UpdatedAt = $eventContext.occurred

  children comments id commentId
    from CommentAdded key commentId
      parent postId
      AuthorId = authorId
      Content = content
      CreatedAt = $eventContext.occurred

    from CommentEdited key commentId
      parent postId
      Content = content
      EditedAt = $eventContext.occurred

    remove with CommentDeleted key commentId
      parent postId

    join User on AuthorId
      events UserRegistered
      AuthorName = name
```

### Multi-Level Nesting

```pdl
projection Company => CompanyReadModel
  from CompanyCreated
    Name = name

  children departments id deptId
    from DepartmentCreated key deptId
      parent companyId
      Name = name

    children teams id teamId
      from TeamCreated key teamId
        parent deptId
        Name = name

      children members id memberId
        from MemberAdded key memberId
          parent teamId
          Name = name
          Role = role
```

## Parent Key Expressions

The parent key can use various expressions:

```pdl
children items id itemId
  from ItemAdded key itemId
    parent orderId                        # Event property
    # or
    parent $eventContext.eventSourceId    # Event source ID
    # or
    parent order.id                       # Nested property
```

## AutoMap with Children

AutoMap at the children level applies to all child events:

```pdl
children members id userId
  automap

  from UserAdded key userId
    parent groupId
    # Name, Email, etc. are auto-mapped

  from UserUpdated key userId
    parent groupId
    # Updates are auto-mapped
```

## Collection Property

The children block maps to a collection property on the read model:

```csharp
public class GroupReadModel
{
    public string Name { get; set; }
    public List<GroupMember> Members { get; set; } = new();
}

public class GroupMember
{
    public string UserId { get; set; }
    public string Name { get; set; }
    public string Role { get; set; }
}
```

## Best Practices

1. **Clear Identifiers**: Use meaningful identifiers that clearly identify children
2. **Parent Keys**: Always specify parent keys to maintain relationships
3. **Removal**: Include removal logic for children that can be deleted
4. **Joins for Enrichment**: Use joins to add related data to children
5. **Nested Carefully**: Deep nesting can impact performance and complexity
6. **AutoMap Selectively**: Use AutoMap for children when property names align
7. **Consistent Patterns**: Use consistent event patterns across children

## Common Patterns

### Add/Update/Remove

```pdl
children items id itemId
  from ItemAdded key itemId
    parent parentId
    # properties

  from ItemUpdated key itemId
    parent parentId
    # updated properties

  remove with ItemRemoved key itemId
    parent parentId
```

### Enrichment with Joins

```pdl
children members id userId
  from MemberAdded key userId
    parent groupId
    UserId = userId

  join User on UserId
    events UserCreated, UserUpdated
    Name = name
    Email = email
```pdl

### Versioning

```pdl
children versions id versionNumber
  from VersionCreated key versionNumber
    parent documentId
    Content = content
    CreatedAt = $eventContext.occurred
    CreatedBy = authorId
```

## See Also

- [Joins](/chronicle/projections/projection-declaration-language/joins/) - Enriching children with related data
- [Removal](/chronicle/projections/projection-declaration-language/removal/) - Removing children when events occur
- [Keys](/chronicle/projections/projection-declaration-language/keys/) - Understanding child and parent keys
