Введение в работу с базами данных на Swift
Swift давно перестал быть языком исключительно для мобильной разработки. С появлением серверных фреймворков, таких как Vapor и Kitura, Swift стал полноценным инструментом для создания backend-решений. Ключевой аспект любой серверной системы — это работа с базами данных. В этой статье мы рассмотрим, как подключаться и взаимодействовать с двумя популярными СУБД: реляционной PostgreSQL и документо-ориентированной MongoDB. Вы узнаете, какие библиотеки использовать, как настроить подключение и выполнять основные операции CRUD на чистом Swift.
PostgreSQL в Swift: настройка и базовые операции
PostgreSQL — одна из самых надежных реляционных баз данных. Для работы с ней в Swift существует несколько библиотек, но самой популярной является PostgresNIO — асинхронный драйвер, построенный на основе SwiftNIO. Если вы используете фреймворк Vapor, то работа с PostgreSQL упрощается через ORM Fluent.
Подключение к PostgreSQL через PostgresNIO
Начнем с установки зависимости. В Package.swift добавьте:
// swift-tools-version:5.7
import PackageDescription
let package = Package(
name: "MyApp",
dependencies: [
.package(url: "https://github.com/vapor/postgres-nio.git", from: "1.18.0")
],
targets: [
.target(name: "MyApp", dependencies: [
.product(name: "PostgresNIO", package: "postgres-nio")
])
]
)
Пример подключения и выполнения простого запроса SELECT:
import PostgresNIO
import NIOCore
import NIOPosix
let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1)
let config = PostgresConnection.Configuration(
host: "localhost",
port: 5432,
username: "myuser",
password: "mypassword",
database: "mydb",
tls: .disable
)
let connection = try await PostgresConnection.connect(
on: eventLoopGroup.next(),
configuration: config
)
let rows = try await connection.query("SELECT id, name FROM users LIMIT 5;", logger: nil)
for try await row in rows {
let id: Int = try row["id"].decode(Int.self)
let name: String = try row["name"].decode(String.self)
print("User: \(id) - \(name)")
}
Работа с Vapor Fluent (ORM)
Fluent предоставляет высокоуровневый API для работы с PostgreSQL. Модель пользователя будет выглядеть так:
import Fluent
import Vapor
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
}
}
// Создание записи
let user = User(name: "Иван", email: "ivan@example.com")
try await user.save(on: req.db)
// Запрос всех пользователей
let users = try await User.query(on: req.db).all()
MongoDB в Swift: работа с документами
MongoDB — это NoSQL база данных, хранящая данные в формате BSON (двоичный JSON). Для Swift существует официальный драйвер MongoSwift, разработанный MongoDB Inc. Он поддерживает асинхронные операции и синхронный режим.
Установка и подключение MongoSwift
Добавьте зависимость в Package.swift:
dependencies: [
.package(url: "https://github.com/mongodb/mongo-swift-driver.git", from: "1.3.0")
],
targets: [
.target(name: "MyApp", dependencies: [
.product(name: "MongoSwift", package: "mongo-swift-driver")
])
]
Пример подключения к локальной MongoDB и вставки документа:
import MongoSwift
let client = try MongoClient("mongodb://localhost:27017")
let db = client.db("mydatabase")
let collection = db.collection("users")
// Создание документа
let document: Document = [
"name": "Анна",
"age": 28,
"skills": ["Swift", "iOS", "MongoDB"]
]
let result = try collection.insertOne(document)
print("Вставлен документ с id: \(result?.insertedID ?? "")")
// Поиск документа
let query: Document = ["name": "Анна"]
if let found = try collection.findOne(query) {
print("Найден: \(found)")
}
Асинхронная работа с MongoDB
MongoSwift поддерживает async/await. Пример асинхронного поиска:
import MongoSwift
let client = try MongoClient("mongodb://localhost:27017")
let collection = client.db("test").collection("products")
struct Product: Codable {
let name: String
let price: Double
}
let cursor = try await collection.find(["price": ["$gt": 100.0]])
for try await doc in cursor {
let product = try BSONDecoder().decode(Product.self, from: doc)
print("Товар: \(product.name) - \(product.price) руб.")
}
Сравнение PostgreSQL и MongoDB для Swift-разработки
Выбор между PostgreSQL и MongoDB зависит от структуры ваших данных и требований к проекту. Рассмотрим ключевые отличия:
- Схема данных: PostgreSQL требует строгой схемы (таблицы, типы), MongoDB — гибкая схема (документы могут отличаться).
- Производительность: MongoDB быстрее на операциях записи и чтения при работе с большими объемами неструктурированных данных. PostgreSQL эффективнее для сложных JOIN-запросов и транзакций.
- Инструменты Swift: Для PostgreSQL — PostgresNIO и Fluent (Vapor). Для MongoDB — MongoSwift и его обертки.
- Транзакции: PostgreSQL поддерживает ACID-транзакции на уровне базы. MongoDB — multi-document транзакции (с версии 4.0).
- Типизация: В Swift с PostgreSQL через Fluent вы получаете строгую типизацию на уровне моделей. MongoDB требует декодирования BSON в структуры.
Заключение
Swift уверенно занимает нишу серверной разработки, и работа с базами данных — неотъемлемая часть этого процесса. PostgreSQL и MongoDB предоставляют отличные драйверы для Swift, позволяя строить как высоконагруженные реляционные системы, так и гибкие документо-ориентированные приложения. Для начинающих серверных разработчиков на Swift рекомендуется начать с Vapor + Fluent (PostgreSQL), так как это дает готовую инфраструктуру и ORM. Если ваш проект требует хранения JSON-подобных данных с возможностью быстрой итерации схемы — MongoDB станет луч