Introducción: Bases de datos en el ecosistema Swift
Swift ha superado hace tiempo el desarrollo de aplicaciones móviles simples. Con la aparición de frameworks del lado del servidor como Vapor y Perfect, el lenguaje se ha convertido en una herramienta completa para construir backends. Sin embargo, trabajar con bases de datos en Swift tiene sus propias particularidades. A diferencia de Python o JavaScript, aquí no hay controladores incorporados, todo se maneja a través de paquetes de terceros.
En este artículo, analizaremos cómo conectarse a dos sistemas de gestión de bases de datos populares: el relacional PostgreSQL y el orientado a documentos MongoDB. Aprenderás qué bibliotecas usar, cómo configurar la conexión y cómo realizar operaciones CRUD básicas. Los ejemplos están orientados a iOS/macOS, pero el código también funcionará en un entorno de servidor.
PostgreSQL en Swift: Enfoque clásico con Vapor y Fluent
Elección de la biblioteca
Para trabajar con PostgreSQL en Swift, el estándar de facto es Fluent, un ORM del framework Vapor. Fluent soporta PostgreSQL, MySQL, SQLite y MongoDB (a través de un controlador separado). Si necesitas trabajar sin Vapor, usa PostgresClientKit, un controlador de bajo nivel.
Configuración de la conexión
Añade la dependencia a Package.swift:
.package(url: "https://github.com/vapor/fluent-postgres-driver.git", from: "2.0.0")Configuración básica en configure.swift:
import Fluentimport FluentPostgresDriverimport Vapor
public func configure(_ app: Application) throws { app.databases.use(.postgres( hostname: "localhost", port: 5432, username: "swift_user", password: "secret", database: "swift_db" ), as: .psql) // Agregar migraciones app.migrations.add(CreateUser())}Operaciones CRUD usando el modelo User como ejemplo
Creemos un modelo y una migración:
final class User: Model, Content { static let schema = "users" @ID(key: .id) var id: UUID? @Field(key: "name") var name: String @Field(key: "email") var email: String init() { } init(id: UUID? = nil, name: String, email: String) { self.id = id self.name = name self.email = email }}
struct CreateUser: Migration { func prepare(on database: Database) -> EventLoopFuture<Void> { database.schema("users") .id() .field("name", .string, .required) .field("email", .string, .required) .create() } func revert(on database: Database) -> EventLoopFuture<Void> { database.schema("users").delete() }}Ejemplo de consulta en un controlador:
// Crear un usuariouser = User(name: "Alexey", email: "alex@example.com")try await user.save(on: req.db)
// Encontrar todos los usuarioslet users = try await User.query(on: req.db).all()
// Filtrar por emaillet filtered = try await User.query(on: req.db) .filter(\\.$email == "alex@example.com") .first()Importante: Fluent usa asincronía mediante EventLoopFuture o async/await (a partir de Vapor 4.60+). Asegúrate de que tu entorno soporte Swift 5.5+.
MongoDB en Swift: Flexibilidad de documentos con MongoKitten
Elección del controlador
Para MongoDB, la biblioteca principal es MongoKitten. Soporta todas las versiones modernas de MongoDB, incluyendo Atlas (versión en la nube). Una alternativa es MongoSwift de MongoDB Inc., pero MongoKitten se considera más "estilo Swift".
Conectando a la base de datos
Añade a Package.swift:
.package(url: "https://github.com/OpenKitten/MongoKitten.git", from: "7.0.0")Ejemplo de conexión (para iOS/macOS):