Rohzugriff
Es ist oft notwendig, direkt auf die Datenbank zuzugreifen, z. B. um eine SQL-Query auszuführen, die vom ORM nicht unterstützt wird.
Das kann über die raw
Method der Database
Class erfolgen.
import { PrimaryKey, AutoIncrement, @entity } from '@deepkit/type'; import { Database } from '@deepkit/orm'; import { sql } from '@deepkit/sql'; import { SqliteDatabaseAdapter } from '@deepkit/sqlite'; @entity.collection('users') class User { id: number & PrimaryKey & AutoIncrement = 0; created: Date = new Date; constructor(public username: string) {} } const database = new Database(new SQLiteDatabaseAdapter(':memory:'), [User]); const query = 'Pet%'; const rows = await database.raw<User>(sql`SELECT * FROM users WHERE username LIKE ${query}`).find(); const result = await database.raw<{ count: number }>(sql`SELECT count(*) as count FROM users WHERE username LIKE ${query}`).findOne(); console.log('Found', result.count, 'users');
Die SQL-Query wird mit dem sql
Template-String-Tag aufgebaut. Dies ist ein spezielles Template-String-Tag, das erlaubt, Werte als Parameter zu übergeben. Diese Parameter werden dann automatisch geparst und in ein sicheres Prepared Statement konvertiert. Das ist wichtig, um SQL-Injection-Angriffe zu vermeiden.
Um einen dynamischen Identifier wie einen Spaltennamen zu übergeben, kann identifier
verwendet werden:
import { identifier, sql } from '@deepkit/sql'; let column = 'username'; const rows = await database.raw<User>(sql`SELECT * FROM users WHERE ${identifier(column)} LIKE ${query}`).find();
Für SQL-Adapter gibt die raw
Method eine RawQuery
mit den findOne
- und find
-Methods zurück, um die Resultate abzurufen. Um eine SQL-Anweisung ohne Rückgabe von Zeilen auszuführen, wie UPDATE/DELETE/etc., kann execute
verwendet werden:
let username = 'Peter'; await database.raw(sql`UPDATE users SET username = ${username} WHERE id = 1`).execute();
RawQuery
unterstützt außerdem das Auslesen des finalen SQL-Strings und der Parameter, korrekt formatiert für den Datenbank-Adapter:
const query = database.raw(sql`SELECT * FROM users WHERE username LIKE ${query}`); console.log(query.sql); console.log(query.params);
Auf diese Weise kann das SQL z. B. in einem anderen Datenbank-Client ausgeführt werden.
Types
Beachte, dass an raw
jeder Type übergeben werden kann und das Resultat aus der Datenbank automatisch in diesen Type konvertiert wird. Das ist besonders nützlich für SQL-Adapter, bei denen eine Class übergeben werden kann und das Resultat automatisch in diese Class konvertiert wird.
Das hat jedoch Einschränkungen. SQL-Joins werden auf diese Weise nicht unterstützt. Wenn Joins verwendet werden sollen, muss der Query Builder des ORM genutzt werden.
Mongo
Der MongoDB-Adapter funktioniert etwas anders, da er nicht auf SQL-Queries basiert, sondern auf Mongo-Commands.
Ein Command kann eine Aggregation-Pipeline, eine find-Query oder ein Write-Command sein.
import { MongoDatabaseAdapter } from '@deepkit/mongo'; const database = new Database(MongoDatabaseAdapter('mongodb://localhost:27017/mydatabase')); // Erstes Argument ist die Entry-Point-Collection, zweites ist der Return Type des Commands const items = await database.raw<ChatMessage, { count: number }>([ { $match: { roomId: 'room1' } }, { $group: { _id: '$userId', count: { $sum: 1 } } }, ]).find();