## Query by Id

Now that you were able to make a mutation, take the `Id` that was printed out and use it in your query to retrieve data.

<BlockSwitcher>

<Block name="Async/Await">

```swift
func getTodo() async {
    do {
        let result = try await Amplify.API.query(
           request: .get(Todo.self, byId: "9FCF5DD5-1D65-4A82-BE76-42CB438607A0")
        )

        switch result {
        case .success(let todo):
            guard let todo = todo else {
                print("Could not find todo")
                return
            }
            print("Successfully retrieved todo: \(todo)")
        case .failure(let error):
            print("Got failed result with \(error.errorDescription)")
        }
    } catch let error as APIError {
        print("Failed to query todo: ", error)
    } catch {
        print("Unexpected error: \(error)")
    }
}
```

</Block>

<Block name="Combine">

```swift
func getTodo() -> AnyCancellable {
    let sink = Amplify.Publisher.create {
        try await Amplify.API.query(
            request: .get(Todo.self, byId: "9FCF5DD5-1D65-4A82-BE76-42CB438607A0")
        )
    }
    .sink {
        if case let .failure(error) = $0 {
            print("Got failed event with error \(error)")
        }
    }
    receiveValue: { result in
        switch result {
        case .success(let todo):
            guard let todo = todo else {
                print("Could not find todo")
                return
            }
            print("Successfully retrieved todo: \(todo)")
        case .failure(let error):
            print("Got failed result with \(error.errorDescription)")
        }
    }
    return sink
}
```

</Block>

</BlockSwitcher>

## List Query

You can get the list of items using `.list` with optional parameters `limit` and `where` to specify the page size and condition. By default, the page size is 1000.


<BlockSwitcher>

<Block name="Async/Await">

```swift
func listTodos() async {
    let todo = Todo.keys
    let predicate = todo.name == "my first todo" && todo.description == "todo description"
    let request = GraphQLRequest<Todo>.list(Todo.self, where: predicate, limit: 1000)
    do {
        let result = try await Amplify.API.query(request: request)
        switch result {
        case .success(let todos):
            print("Successfully retrieved list of todos: \(todos)")
        case .failure(let error):
            print("Got failed result with \(error.errorDescription)")
        }
    } catch let error as APIError {
        print("Failed to query list of todos: ", error)
    } catch {
        print("Unexpected error: \(error)")
    }
}
```

</Block>

<Block name="Combine">

```swift
func listTodos() -> AnyCancellable {
    let todo = Todo.keys
    let predicate = todo.name == "my first todo" && todo.description == "todo description"
    let request = GraphQLRequest<Todo>.list(Todo.self, where: predicate, limit: 1000)
    let sink = Amplify.Publisher.create {
        try await Amplify.API.query(request: request)
    }
    .sink {
        if case let .failure(error) = $0 {
            print("Got failed event with error \(error)")
        }
    }
    receiveValue: { result in
    switch result {
        case .success(let todos):
            print("Successfully retrieved list of todos: \(todos)")
        case .failure(let error):
            print("Got failed result with \(error.errorDescription)")
        }
    }
    return sink
}
```

</Block>

</BlockSwitcher>

### List subsequent pages of items

If you are using SwiftUI and have SwiftUI imported in the same code file, you will need to import the class `Amplify.List` to resolve name collision with `SwiftUI.List`:

```swift 
import SwiftUI
import Amplify
import class Amplify.List
```

For large data sets, you'll need to paginate through the results. After receiving the first page of results, you can check if there is a subsequent page and obtain the next page.

```swift
var todos: [Todo] = []
var currentPage: List<Todo>?

func listFirstPage() async {
    let todo = Todo.keys
    let predicate = todo.name == "my first todo" && todo.description == "todo description"
    let request = GraphQLRequest<Todo>.list(Todo.self, where: predicate, limit: 1000)
    do {
        let result = try await Amplify.API.query(request: request)
        switch result {
        case .success(let todos):
            print("Successfully retrieved list of todos: \(todos)")
            self.currentPage = todos
            self.todos.append(contentsOf: todos)
        case .failure(let error):
            print("Got failed result with \(error.errorDescription)")
        }
    } catch let error as APIError {
        print("Failed to query list of todos: ", error)
    } catch {
        print("Unexpected error: \(error)")
    }
}

func listNextPage() async {
    if let current = self.currentPage, current.hasNextPage() {
        do {
            let todos = try await current.getNextPage()
            self.todos.append(contentsOf: todos)
            self.currentPage = todos
        } catch {
            print("Failed to get next page \(error)")
        }
    }
}
```

## List all pages

If you want to get all pages, retrieve the subsequent page when you have successfully retrieved the first or next page.

1. Update the above method `listFirstPage()` to `listAllPages()`
2. Call `listNextPageRecursively()` in the success block of the query in `listAllPages()`
2. Update the `listNextPage()` to `listNextPageRecursively()`
3. Call `listNextPageRecursively()` in the success block of the query in `listNextPageRecursively()`

The completed changes should look like this:

```swift
var todos: [Todo] = []
var currentPage: List<Todo>?

func listAllPages() async { // 1. Updated from `listFirstPage()`
    let todo = Todo.keys
    let predicate = todo.name == "my first todo" && todo.description == "todo description"
    let request = GraphQLRequest<Todo>.list(Todo.self, where: predicate, limit: 1000)
    do {
        let result = try await Amplify.API.query(request: request)
        switch result {
        case .success(let todos):
            print("Successfully retrieved list of todos: \(todos)")
            self.currentPage = todos
            self.todos.append(contentsOf: todos)
            await self.listNextPageRecursively() // 2. Added
        case .failure(let error):
            print("Got failed result with \(error.errorDescription)")
        }
    } catch let error as APIError {
        print("Failed to query list of todos: ", error)
    } catch {
        print("Unexpected error: \(error)")
    }
}

func listNextPageRecursively() async { // 3. Updated from `listNextPage()`
    if let current = currentPage, current.hasNextPage() {
        do {
            let todos = try await current.getNextPage()
            self.todos.append(contentsOf: todos)
            self.currentPage = todos
            await self.listNextPageRecursively() // 4. Added
        } catch {
            print("Failed to get next page \(error)")
        }
    }
}
```
