Konverter, der von withConverter()
verwendet wird, um Benutzerobjekte vom Typ AppModelType
in Firestore-Daten vom Typ DbModelType
umzuwandeln .
Mit dem Konverter können Sie beim Speichern und Abrufen von Objekten aus Firestore generische Typargumente angeben.
In diesem Zusammenhang ist ein „AppModel“ eine Klasse, die in einer Anwendung verwendet wird, um verwandte Informationen und Funktionen zusammenzufassen. Eine solche Klasse könnte beispielsweise Eigenschaften mit komplexen, verschachtelten Datentypen, Eigenschaften für die Memoisierung oder Eigenschaften von Typen haben, die von Firestore nicht unterstützt werden (z. B. symbol
und bigint
. ) und Hilfsfunktionen, die zusammengesetzte Operationen ausführen. Solche Klassen eignen sich nicht und/oder können nicht in einer Firestore-Datenbank gespeichert werden. Stattdessen müssen Instanzen solcher Klassen in „einfache alte JavaScript-Objekte“ (POJOs) mit ausschließlich primitiven Eigenschaften konvertiert werden, die möglicherweise in anderen POJOs oder Arrays von POJOs verschachtelt sind. In diesem Zusammenhang wird dieser Typ als „DbModel“ bezeichnet und wäre ein Objekt, das sich für die Beibehaltung im Firestore eignet. Der Einfachheit halber können Anwendungen FirestoreDataConverter
implementieren und den Konverter bei Firestore-Objekten wie DocumentReference
oder Query
registrieren , um AppModel
beim Speichern im Firestore automatisch in DbModel
zu konvertieren und DbModel
beim Abrufen aus Firestore automatisch in AppModel
zu konvertieren.
Unterschrift:
export declare interface FirestoreDataConverter<AppModelType, DbModelType extends DocumentData = DocumentData>
Methoden
Methode | Beschreibung |
---|---|
fromFirestore(Snapshot, Optionen) | Wird vom Firestore SDK aufgerufen, um Firestore-Daten in ein Objekt vom Typ AppModelType zu konvertieren. Sie können auf Ihre Daten zugreifen, indem Sie Folgendes aufrufen: snapshot.data(options) . Im Allgemeinen können die von snapshot.data() zurückgegebenen Daten in DbModelType umgewandelt werden; Dies kann jedoch nicht garantiert werden, da Firestore kein Schema für die Datenbank erzwingt. Beispielsweise könnten Schreibvorgänge aus einer früheren Version der Anwendung oder Schreibvorgänge von einem anderen Client, der keinen Typkonverter verwendet, Daten mit unterschiedlichen Eigenschaften und/oder Eigenschaftstypen geschrieben haben. Die Implementierung muss entscheiden, ob eine ordnungsgemäße Wiederherstellung bei nicht konformen Daten erfolgen soll oder ob ein Fehler ausgegeben werden soll. Informationen zum Überschreiben dieser Methode finden Sie unter . |
toFirestore(modelObject) | Wird vom Firestore SDK aufgerufen, um ein benutzerdefiniertes Modellobjekt vom Typ AppModelType in ein einfaches JavaScript-Objekt (geeignet zum direkten Schreiben in die Firestore-Datenbank) vom Typ DbModelType zu konvertieren. Um set() mit merge und mergeFields zu verwenden, muss toFirestore() mit PartialWithFieldValue<AppModelType> definiert werden. Der Typ WithFieldValue<T> erweitert T , um auch die Verwendung von FieldValues wie deleteField() als Eigenschaftswerte zu ermöglichen. |
toFirestore(modelObject, Optionen) | Wird vom Firestore SDK aufgerufen, um ein benutzerdefiniertes Modellobjekt vom Typ AppModelType in ein einfaches JavaScript-Objekt (geeignet zum direkten Schreiben in die Firestore-Datenbank) vom Typ DbModelType zu konvertieren. Wird mit setDoc() verwendet und mit merge:true oder mergeFields . Der Typ PartialWithFieldValue<T> erweitert Partial<T> , um die Verwendung von FieldValues wie arrayUnion() als Eigenschaftswerte zu ermöglichen. Es unterstützt auch verschachtelte Partial , indem es das Weglassen verschachtelter Felder ermöglicht. |
FirestoreDataConverter.fromFirestore()
Wird vom Firestore SDK aufgerufen, um Firestore-Daten in ein Objekt vom Typ AppModelType
zu konvertieren . Sie können auf Ihre Daten zugreifen, indem Sie Folgendes aufrufen: snapshot.data(options)
.
Im Allgemeinen können die von snapshot.data()
zurückgegebenen Daten in DbModelType
umgewandelt werden ; Dies kann jedoch nicht garantiert werden, da Firestore kein Schema für die Datenbank erzwingt. Beispielsweise könnten Schreibvorgänge aus einer früheren Version der Anwendung oder Schreibvorgänge von einem anderen Client, der keinen Typkonverter verwendet, Daten mit unterschiedlichen Eigenschaften und/oder Eigenschaftstypen geschrieben haben. Die Implementierung muss entscheiden, ob eine ordnungsgemäße Wiederherstellung bei nicht konformen Daten erfolgen soll oder ob ein Fehler ausgegeben werden soll.
Informationen zum Überschreiben dieser Methode finden Sie unter .
Unterschrift:
fromFirestore(snapshot: QueryDocumentSnapshot<DocumentData, DocumentData>, options?: SnapshotOptions): AppModelType;
Parameter
Parameter | Typ | Beschreibung |
---|---|---|
Schnappschuss | QueryDocumentSnapshot < Dokumentdaten , Dokumentdaten > | Ein QueryDocumentSnapshot , der Ihre Daten und Metadaten enthält. |
Optionen | SnapshotOptions | Die SnapshotOptions vom ersten Aufruf von data() . |
Kehrt zurück:
AppModelType
FirestoreDataConverter.toFirestore()
Wird vom Firestore SDK aufgerufen, um ein benutzerdefiniertes Modellobjekt vom Typ AppModelType
in ein einfaches JavaScript-Objekt (geeignet zum direkten Schreiben in die Firestore-Datenbank) vom Typ DbModelType
zu konvertieren . So verwenden Sie set()
mit merge
und mergeFields
, toFirestore()
muss mit PartialWithFieldValue<AppModelType>
definiert werden .
Der Typ WithFieldValue<T>
erweitert T
, um auch die Verwendung von FieldValues wie deleteField() als Eigenschaftswerte zu ermöglichen.
Unterschrift:
toFirestore(modelObject: WithFieldValue<AppModelType>): WithFieldValue<DbModelType>;
Parameter
Parameter | Typ | Beschreibung |
---|---|---|
modelObject | WithFieldValue <AppModelType> |
Kehrt zurück:
WithFieldValue <DbModelType>
FirestoreDataConverter.toFirestore()
Wird vom Firestore SDK aufgerufen, um ein benutzerdefiniertes Modellobjekt vom Typ AppModelType
in ein einfaches JavaScript-Objekt (geeignet zum direkten Schreiben in die Firestore-Datenbank) vom Typ DbModelType
zu konvertieren . Wird mit setDoc() verwendet und mit merge:true
oder mergeFields
.
Der Typ PartialWithFieldValue<T>
erweitert Partial<T>
, um die Verwendung von FieldValues wie arrayUnion() als Eigenschaftswerte zu ermöglichen. Es unterstützt auch verschachtelte Partial
, indem es das Weglassen verschachtelter Felder ermöglicht.
Unterschrift:
toFirestore(modelObject: PartialWithFieldValue<AppModelType>, options: SetOptions): PartialWithFieldValue<DbModelType>;
Parameter
Parameter | Typ | Beschreibung |
---|---|---|
modelObject | PartialWithFieldValue <AppModelType> | |
Optionen | SetOptions |
Kehrt zurück:
PartialWithFieldValue <DbModelType>
Beispiel
Einfaches Beispiel
const numberConverter = {
toFirestore(value: WithFieldValue<number>) {
return { value };
},
fromFirestore(snapshot: QueryDocumentSnapshot, options: SnapshotOptions) {
return snapshot.data(options).value as number;
}
};
async function simpleDemo(db: Firestore): Promise<void> {
const documentRef = doc(db, 'values/value123').withConverter(numberConverter);
// converters are used with `setDoc`, `addDoc`, and `getDoc`
await setDoc(documentRef, 42);
const snapshot1 = await getDoc(documentRef);
assertEqual(snapshot1.data(), 42);
// converters are not used when writing data with `updateDoc`
await updateDoc(documentRef, { value: 999 });
const snapshot2 = await getDoc(documentRef);
assertEqual(snapshot2.data(), 999);
}
Erweitertes Beispiel
// The Post class is a model that is used by our application.
// This class may have properties and methods that are specific
// to our application execution, which do not need to be persisted
// to Firestore.
class Post {
constructor(
readonly title: string,
readonly author: string,
readonly lastUpdatedMillis: number
) {}
toString(): string {
return `${this.title} by ${this.author}`;
}
}
// The PostDbModel represents how we want our posts to be stored
// in Firestore. This DbModel has different properties (`ttl`,
// `aut`, and `lut`) from the Post class we use in our application.
interface PostDbModel {
ttl: string;
aut: { firstName: string; lastName: string };
lut: Timestamp;
}
// The `PostConverter` implements `FirestoreDataConverter` and specifies
// how the Firestore SDK can convert `Post` objects to `PostDbModel`
// objects and vice versa.
class PostConverter implements FirestoreDataConverter<Post, PostDbModel> {
toFirestore(post: WithFieldValue<Post>): WithFieldValue<PostDbModel> {
return {
ttl: post.title,
aut: this._autFromAuthor(post.author),
lut: this._lutFromLastUpdatedMillis(post.lastUpdatedMillis)
};
}
fromFirestore(snapshot: QueryDocumentSnapshot, options: SnapshotOptions): Post {
const data = snapshot.data(options) as PostDbModel;
const author = `${data.aut.firstName} ${data.aut.lastName}`;
return new Post(data.ttl, author, data.lut.toMillis());
}
_autFromAuthor(
author: string | FieldValue
): { firstName: string; lastName: string } | FieldValue {
if (typeof author !== 'string') {
// `author` is a FieldValue, so just return it.
return author;
}
const [firstName, lastName] = author.split(' ');
return {firstName, lastName};
}
_lutFromLastUpdatedMillis(
lastUpdatedMillis: number | FieldValue
): Timestamp | FieldValue {
if (typeof lastUpdatedMillis !== 'number') {
// `lastUpdatedMillis` must be a FieldValue, so just return it.
return lastUpdatedMillis;
}
return Timestamp.fromMillis(lastUpdatedMillis);
}
}
async function advancedDemo(db: Firestore): Promise<void> {
// Create a `DocumentReference` with a `FirestoreDataConverter`.
const documentRef = doc(db, 'posts/post123').withConverter(new PostConverter());
// The `data` argument specified to `setDoc()` is type checked by the
// TypeScript compiler to be compatible with `Post`. Since the `data`
// argument is typed as `WithFieldValue<Post>` rather than just `Post`,
// this allows properties of the `data` argument to also be special
// Firestore values that perform server-side mutations, such as
// `arrayRemove()`, `deleteField()`, and `serverTimestamp()`.
await setDoc(documentRef, {
title: 'My Life',
author: 'Foo Bar',
lastUpdatedMillis: serverTimestamp()
});
// The TypeScript compiler will fail to compile if the `data` argument to
// `setDoc()` is _not_ compatible with `WithFieldValue<Post>`. This
// type checking prevents the caller from specifying objects with incorrect
// properties or property values.
// @ts-expect-error "Argument of type { ttl: string; } is not assignable
// to parameter of type WithFieldValue<Post>"
await setDoc(documentRef, { ttl: 'The Title' });
// When retrieving a document with `getDoc()` the `DocumentSnapshot`
// object's `data()` method returns a `Post`, rather than a generic object,
// which would have been returned if the `DocumentReference` did _not_ have a
// `FirestoreDataConverter` attached to it.
const snapshot1: DocumentSnapshot<Post> = await getDoc(documentRef);
const post1: Post = snapshot1.data()!;
if (post1) {
assertEqual(post1.title, 'My Life');
assertEqual(post1.author, 'Foo Bar');
}
// The `data` argument specified to `updateDoc()` is type checked by the
// TypeScript compiler to be compatible with `PostDbModel`. Note that
// unlike `setDoc()`, whose `data` argument must be compatible with `Post`,
// the `data` argument to `updateDoc()` must be compatible with
// `PostDbModel`. Similar to `setDoc()`, since the `data` argument is typed
// as `WithFieldValue<PostDbModel>` rather than just `PostDbModel`, this
// allows properties of the `data` argument to also be those special
// Firestore values, like `arrayRemove()`, `deleteField()`, and
// `serverTimestamp()`.
await updateDoc(documentRef, {
'aut.firstName': 'NewFirstName',
lut: serverTimestamp()
});
// The TypeScript compiler will fail to compile if the `data` argument to
// `updateDoc()` is _not_ compatible with `WithFieldValue<PostDbModel>`.
// This type checking prevents the caller from specifying objects with
// incorrect properties or property values.
// @ts-expect-error "Argument of type { title: string; } is not assignable
// to parameter of type WithFieldValue<PostDbModel>"
await updateDoc(documentRef, { title: 'New Title' });
const snapshot2: DocumentSnapshot<Post> = await getDoc(documentRef);
const post2: Post = snapshot2.data()!;
if (post2) {
assertEqual(post2.title, 'My Life');
assertEqual(post2.author, 'NewFirstName Bar');
}
}