# Geavanceerd Fluent streeft ernaar een algemene, database-agnostische API te maken voor het werken met uw data. Dit maakt het makkelijker om Fluent te leren, ongeacht welke database driver je gebruikt. Het maken van gegeneraliseerde API's kan er ook voor zorgen dat het werken met je database zich meer thuis voelt in Swift. Het kan echter zijn dat u een functie van uw onderliggende database driver moet gebruiken die nog niet door Fluent wordt ondersteund. Deze gids behandelt geavanceerde patronen en API's in Fluent die alleen werken met bepaalde databases. ## SQL Alle SQL database drivers van Fluent zijn gebouwd op [SQLKit](https://github.com/vapor/sql-kit). Deze algemene SQL-implementatie wordt met Fluent meegeleverd in de `FluentSQL` module. ### SQL Database Elke Fluent `Database` kan worden gecast naar een `SQLDatabase`. Dit omvat `req.db`, `app.db`, de `database` doorgegeven aan `Migration`, enz. ```swift import FluentSQL if let sql = req.db as? SQLDatabase { // Het onderliggende databasestuurprogramma is SQL. let planets = try await sql.raw("SELECT * FROM planets").all(decoding: Planet.self) } else { // Het onderliggende databasestuurprogramma is _niet_ SQL. } ``` Deze cast werkt alleen als de onderliggende database driver een SQL database is. Leer meer over `SQLDatabase`'s methodes in [SQLKit's README](https://github.com/vapor/sql-kit). ### Specifieke SQL Database U kunt ook naar specifieke SQL-databases casten door het stuurprogramma te importeren. ```swift import FluentPostgresDriver if let postgres = req.db as? PostgresDatabase { // Het onderliggende databasestuurprogramma is PostgreSQL. postgres.simpleQuery("SELECT * FROM planets").all() } else { // De onderliggende database is _niet_ PostgreSQL. } ``` Op het moment van schrijven worden de volgende SQL drivers ondersteund. |Database|Driver|Library| |-|-|-| |`PostgresDatabase`|[vapor/fluent-postgres-driver](https://github.com/vapor/fluent-postgres-driver)|[vapor/postgres-nio](https://github.com/vapor/postgres-nio)| |`MySQLDatabase`|[vapor/fluent-mysql-driver](https://github.com/vapor/fluent-mysql-driver)|[vapor/mysql-nio](https://github.com/vapor/mysql-nio)| |`SQLiteDatabase`|[vapor/fluent-sqlite-driver](https://github.com/vapor/fluent-sqlite-driver)|[vapor/sqlite-nio](https://github.com/vapor/sqlite-nio)| Bezoek de README van de bibliotheek voor meer informatie over de database-specifieke API's. ### SQL Custom Bijna alle query en schema types van Fluent ondersteunen een `.custom` case. Hiermee kunt u databasefuncties gebruiken die Fluent nog niet ondersteunt. ```swift import FluentPostgresDriver let query = Planet.query(on: req.db) if req.db is PostgresDatabase { // ILIKE ondersteund. query.filter(\.$name, .custom("ILIKE"), "earth") } else { // ILIKE niet ondersteund. query.group(.or) { or in or.filter(\.$name == "earth").filter(\.$name == "Earth") } } query.all() ``` SQL databases ondersteunen zowel `String` als `SQLExpression` in alle `.custom` gevallen. De `FluentSQL` module biedt handige methodes voor veel voorkomende gevallen. ```swift import FluentSQL let query = Planet.query(on: req.db) if req.db is SQLDatabase { // Het onderliggende databasestuurprogramma is SQL. query.filter(.sql(raw: "LOWER(name) = 'earth'")) } else { // Het onderliggende databasestuurprogramma is _niet_ SQL. } ``` Hieronder staat een voorbeeld van `.custom` via het `.sql(raw:)` gemak dat wordt gebruikt met de schema bouwer. ```swift import FluentSQL let builder = database.schema("planets").id() if database is MySQLDatabase { // Het onderliggende databasestuurprogramma is MySQL. builder.field("name", .sql(raw: "VARCHAR(64)"), .required) } else { // Het onderliggende databasestuurprogramma is _niet_ MySQL. builder.field("name", .string, .required) } builder.create() ``` ## MongoDB Fluent MongoDB is een integratie tussen [Fluent](../fluent/overview.md) en de [MongoKitten](https://github.com/OpenKitten/MongoKitten/) driver. Het maakt gebruik van het sterke typesysteem van Swift en de database agnostische interface van Fluent met MongoDB. De meest voorkomende identifier in MongoDB is ObjectId. U kunt deze gebruiken voor uw project met `@ID(custom: .id)`. Als u dezelfde modellen met SQL wilt gebruiken, gebruik dan niet `ObjectId`. Gebruik in plaats daarvan `UUID`. ```swift final class User: Model { // Naam van de tabel of verzameling. static let schema = "users" // Unieke identificatie voor deze Gebruiker. // In dit geval wordt ObjectId gebruikt // Fluent raadt aan om standaard UUID te gebruiken, maar ObjectId wordt ook ondersteund @ID(custom: .id) var id: ObjectId? // Het e-mailadres van de gebruiker @Field(key: "email") var email: String // Het wachtwoord van de gebruiker wordt opgeslagen als een BCrypt hash @Field(key: "password") var passwordHash: String // Creëert een nieuwe, lege User instantie, voor gebruik door Fluent init() { } // Creëert een nieuwe Gebruiker met alle eigenschappen ingesteld. init(id: ObjectId? = nil, email: String, passwordHash: String, profile: Profile) { self.id = id self.email = email self.passwordHash = passwordHash self.profile = profile } } ``` ### Data Modelleren In MongoDB worden Modellen op dezelfde manier gedefinieerd als in elke andere Fluent omgeving. Het belangrijkste verschil tussen SQL-databases en MongoDB ligt in relaties en architectuur. In SQL-omgevingen, is het heel gebruikelijk om join tabellen voor relaties tussen twee entiteiten te creëren. In MongoDB, echter, kan een array worden gebruikt om gerelateerde identifiers op te slaan. Door het ontwerp van MongoDB is het efficiënter en praktischer om uw modellen te ontwerpen met geneste gegevensstructuren. ### Flexibele Data U kunt flexibele gegevens toevoegen in MongoDB, maar deze code zal niet werken in SQL-omgevingen. Om gegroepeerde willekeurige data opslag te maken kun je `Document` gebruiken. ```swift @Field(key: "document") var document: Document ``` Fluent kan geen query's van strikte types op deze waarden ondersteunen. U kunt een met punten genoteerd sleutelpad in uw query gebruiken om query's uit te voeren. Dit wordt in MongoDB geaccepteerd om toegang te krijgen tot geneste waarden. ```swift Something.query(on: db).filter("document.key", .equal, 5).first() ``` ### Gebruik van reguliere expressies Door een reguliere expressie door te geven met de `.custom()` case, kan U de MongoDB raadplegen. [MongoDB](https://www.mongodb.com/docs/manual/reference/operator/query/regex/) accepteert reguliere expressies die compatibel zijn met Perl. Zo kan U bijvoorbeeld zoeken naar hoofdletterongevoelige tekens onder het veld `naam`: ```swift import FluentMongoDriver var queryDocument = Document() queryDocument["name"]["$regex"] = "e" queryDocument["name"]["$options"] = "i" let planets = try Planet.query(on: req.db).filter(.custom(queryDocument)).all() ``` Dit geeft planeten terug die 'e' en 'E' bevatten. U kunt ook elke andere complexe RegEx maken die door MongoDB wordt geaccepteerd. ### Raw Access Om toegang te krijgen tot de ruwe `MongoDatabase` instantie, cast je de database instantie naar `MongoDatabaseRepresentable` als zodanig: ```swift guard let db = req.db as? MongoDatabaseRepresentable else { throw Abort(.internalServerError) } let mongodb = db.raw ``` Vanaf hier kunt u gebruik maken van alle van de MongoKitten API's.