

# Querying Models

Once you have a model (and optionally a migration) you can start querying your database to create, read, update, and delete data.

## Connection

The first thing you need to query your database, is a connection to it. Luckily, they are easy to get.

You can use either the application or an incoming request to create a database connection. You just need access to the `DatabaseIdentifier`.

### Request

The preferred method for getting access to a database connection is via an incoming request.

    router.get(...) { req in
        return req.withConnection(to: .foo) { db in
            // use the db here
        }
    }

The first parameter is the database's identifier. The second parameter is a closure that accepts a connection to that database.

Tip

Although the closure to `.withConnection(to: ...)` accepts a database connection, we often use just `db` for short.

The closure is expected to return a `Future<Void>`. When this future is completed, the connection will be released back into Fluent's connection pool. This is usually acheived by simply returning the query as we will soon see.

### Application

You can also create a database connection using the application. This is useful for cases where you must access the database from outside a request/response event.

    let res = app.withConnection(to: .foo) { db in
        // use the db here
    }
    print(res) // Future<T>

This is usually done in the boot section of your application.

Warning

Do not use database connections created by the application in a route closure (when responding to a request). Always use the incoming request to create a connection to avoid threading issues.

## Create

To create (save) a model to the database, first initialize an instance of your model, then call `.save(on: )`.

    router.post(...) { req in
        return req.withConnection(to: .foo) { db -> Future<User> in
            let user = User(name: "Vapor", age: 3)
            return user.save(on: db).transform(to: user) // Future<User>
        }
    }

### Response

`.save(on: )` returns a `Future<Void>` that completes when the user has finished saving. In this example, we then map that `Future<Void>` to a `Future<User>` by calling `.map` and passing in the recently-saved user.

You can also use `.map` to return a simple success response.

    router.post(...) { req in
        return req.withConnection(to: .foo) { db -> Future<HTTPResponse> in
            let user = User(name: "Vapor", age: 3)
            return user.save(on: db).map(to: HTTPResponse.self) {
                return HTTPResponse(status: .created)
            }
        }
    }

### Multiple

If you have multiple instances to save, do so using an array. Arrays containing only futures behave like futures.

    router.post(...) { req in
        return req.withConnection(to: .foo) { db -> Future<HTTPResponse> in
            let marie = User(name: "Marie Curie", age: 66)
            let charles = User(name: "Charles Darwin", age: 73)
            return [
                marie.save(on: db),
                charles.save(on: db)
            ].map(to: HTTPResponse.self) {
                return HTTPResponse(status: .created)
            }
        }
    }

## Read

To read models from the database, use `.query()` on the database connection to create a QueryBuilder.

### All

Fetch all instances of a model from the database using `.all()`.

    router.get(...) { req in
        return req.withConnection(to: .foo) { db -> Future<[User]> in
            return db.query(User.self).all()
        }
    }

### Filter

Use `.filter(...)` to apply filters to your query.

    router.get(...) { req in
        return req.withConnection(to: .foo) { db -> Future<[User]> in
            return try db.query(User.self).filter(\User.age > 50).all()
        }
    }

### First

You can also use `.first()` to just get the first result.

    router.get(...) { req in
        return req.withConnection(to: .foo) { db -> Future<User> in
            return try db.query(User.self).filter(\User.name == "Vapor").first().map(to: User.self) { user in
                guard let user = user else {
                    throw Abort(.notFound, reason: "Could not find user.")
                }

                return user
            }
        }
    }

Notice we use `.map(to:)` here to convert the optional user returned by `.first()` to a non-optional user, or we throw an error.

## Update

    router.put(...) { req in
        return req.withConnection(to: .foo) { db -> Future<User> in
            return db.query(User.self).first().map(to: User.self) { user in
                guard let user = $0 else {
                    throw Abort(.notFound, reason: "Could not find user.")
                }

                return user
            }.flatMap(to: User.self) { user in
                user.age += 1
                return user.update(on: db).map(to: User.self) { user }
            }
        }
    }

Notice we use `.map(to:)` here to convert the optional user returned by `.first()` to a non-optional user, or we throw an error.

## Delete

    router.delete(...) { req in
        return req.withConnection(to: .foo) { db -> Future<User> in
            return db.query(User.self).first().map(to: User.self) { user in
                guard let user = $0 else {
                    throw Abort(.notFound, reason: "Could not find user.")
                }
                return user
            }.flatMap(to: User.self) { user in
                return user.delete(on: db).transfom(to: user)
            }
        }
    }

Notice we use `.map(to:)` here to convert the optional user returned by `.first()` to a non-optional user, or we throw an error.