# Defining Views

A view holds the data that queries read. Define the shape of an item as a struct, and call the `NewItemView` function to create a view that holds such items in memory:

```go
type BookItem struct {
  ID            string `json:"id"`
  Title         string `json:"title"`
  Author        string `json:"author"`
  IsBorrowed    bool   `json:"isBorrowed"`
  BorrowedUntil string `json:"borrowedUntil"`
  EventID       string `json:"eventId"`
}

catalog := architecturekit.NewItemView[BookItem]()
```

Keep the ID of the last event in every item, so that a caller can hand it over to a command that uses the `NewIsSubjectOnEventIDPrecondition` function (see [Guarding Against Concurrent Changes](/docs/architecturekit/using-preconditions#guarding-against-concurrent-changes)).

To add an item, call the `Insert` function:

```go
catalog.Insert(BookItem{
  ID:     "42",
  Title:  "2001 – A Space Odyssey",
  Author: "Arthur C. Clarke",
})
```

To change items, call the `Update` function with a function that selects the items and a function that changes them. It returns the number of changed items:

```go
isBook42 := func(item BookItem) bool {
  return item.ID == "42"
}

changed := catalog.Update(isBook42, func(item *BookItem) {
  item.IsBorrowed = true
})
```

To change items or add an item if none matches, call the `Upsert` function and additionally hand over the item to add. It returns the number of changed items, which is `0` if the item was added:

```go
changed := catalog.Upsert(isBook42, func(item *BookItem) {
  item.IsBorrowed = true
}, BookItem{
  ID:         "42",
  IsBorrowed: true,
})
```

To remove items, call the `Delete` function. It returns the number of removed items:

```go
removed := catalog.Delete(isBook42)
```

To read all items, call the `All` function. It returns an iterator over a copy of the items, which you can use e.g. inside a `for range` loop:

```go
items, err := catalog.All(context.TODO())
if err != nil {
  // ...
}

for item := range items {
  // ...
}
```

To keep items somewhere else, for example in a database, implement the `View` interface, which consists of the `All` function:

```go
type BookTable struct {
  // ...
}

func (t *BookTable) All(ctx context.Context) (iter.Seq[BookItem], error) {
  // ...
}
```
