FirestoreDataConverter interface

ממיר בשימוש על ידי withConverter() כדי להפוך אובייקטי משתמש מסוג AppModelType לנתוני Firestore מסוג DbModelType .

השימוש בממיר מאפשר לך לציין ארגומנטים מסוג גנריים בעת אחסון ושליפה של אובייקטים מ-Firestore.

בהקשר זה, "AppModel" הוא מחלקה המשמשת באפליקציה כדי לארוז יחד מידע ופונקציונליות קשורים. מחלקה כזו יכולה, למשל, לכלול מאפיינים עם סוגי נתונים מורכבים ומקוננים, מאפיינים המשמשים לזיכרון, מאפיינים של סוגים שאינם נתמכים על ידי Firestore (כגון symbol bigint ), ופונקציות עוזר המבצעות פעולות מורכבות. שיעורים כאלה אינם מתאימים ו/או אפשריים לאחסון במסד נתונים של Firestore. במקום זאת, יש להמיר מופעים של מחלקות כאלה ל"אובייקטי JavaScript ישנים רגילים" (POJOs) בעלי מאפיינים פרימיטיביים בלבד, שעלולים לקנן בתוך POJOs אחרים או מערכים של POJOs. בהקשר זה, סוג זה מכונה "DbModel" והוא יהיה אובייקט המתאים להתמיד ב-Firestore. מטעמי נוחות, יישומים יכולים ליישם את FirestoreDataConverter ולרשום את הממיר עם אובייקטי Firestore, כגון DocumentReference או Query , להמרה אוטומטית AppModel ל- DbModel בעת אחסון ב-Firestore, ולהמיר DbModel ל- AppModel בעת אחזור מ-Firestore.

חֲתִימָה:

export declare interface FirestoreDataConverter<AppModelType, DbModelType extends DocumentData = DocumentData> 

שיטות

שיטה תיאור
fromFirestore(תמונה, אפשרויות) נקרא על ידי Firestore SDK כדי להמיר נתוני Firestore לאובייקט מסוג AppModelType . אתה יכול לגשת לנתונים שלך על ידי קריאה: snapshot.data(options) . בדרך כלל, ניתן להטיל את הנתונים המוחזרים מ- snapshot.data() ל- DbModelType ; עם זאת, זה לא מובטח מכיוון ש-Firestore לא אוכפת סכימה על מסד הנתונים. לדוגמה, כתיבה מגרסה קודמת של האפליקציה או כתיבה מלקוח אחר שלא השתמש בממיר סוגים יכולה להיות בעלת נתונים כתובים עם מאפיינים ו/או סוגי מאפיינים שונים. היישום יצטרך לבחור אם לשחזר בחן מנתונים שאינם תואמים או לזרוק שגיאה. כדי לעקוף שיטה זו, ראה.
toFirestore(modelObject) נקרא על ידי Firestore SDK להמיר אובייקט דגם מותאם אישית מסוג AppModelType לאובייקט JavaScript רגיל (מתאים לכתיבה ישירות למסד הנתונים של Firestore) מסוג DbModelType . כדי להשתמש set() עם merge ו- mergeFields , יש להגדיר את toFirestore() עם PartialWithFieldValue<AppModelType> . הסוג WithFieldValue<T> מרחיב T כדי לאפשר גם להשתמש ב-FieldValues ​​כגון deleteField() כערכי מאפיינים.
toFirestore(modelObject, options) נקרא על ידי Firestore SDK להמיר אובייקט דגם מותאם אישית מסוג AppModelType לאובייקט JavaScript רגיל (מתאים לכתיבה ישירות למסד הנתונים של Firestore) מסוג DbModelType . בשימוש עם setDoc() , ועם merge:true או mergeFields . הסוג PartialWithFieldValue<T> מרחיב Partial<T> כדי לאפשר שימוש ב-FieldValues ​​כגון arrayUnion() כערכי מאפיינים. הוא תומך גם Partial מקונן על ידי מתן אפשרות להשמטת שדות מקוננים.

FirestoreDataConverter.fromFirestore()

נקרא על ידי Firestore SDK להמיר נתוני Firestore לאובייקט מסוג AppModelType . אתה יכול לגשת לנתונים שלך על ידי קריאה: snapshot.data(options) .

בדרך כלל, ניתן להטיל את הנתונים המוחזרים מ- snapshot.data() ל- DbModelType ; עם זאת, זה לא מובטח מכיוון ש-Firestore לא אוכפת סכימה על מסד הנתונים. לדוגמה, כתיבה מגרסה קודמת של האפליקציה או כתיבה מלקוח אחר שלא השתמש בממיר סוגים יכולה להיות בעלת נתונים כתובים עם מאפיינים ו/או סוגי מאפיינים שונים. היישום יצטרך לבחור אם לשחזר בחן מנתונים שאינם תואמים או לזרוק שגיאה.

כדי לעקוף שיטה זו, ראה.

חֲתִימָה:

fromFirestore(snapshot: QueryDocumentSnapshot<DocumentData, DocumentData>, options?: SnapshotOptions): AppModelType;

פרמטרים

פָּרָמֶטֶר סוּג תיאור
תמונת מצב QueryDocumentSnapshot < DocumentData , DocumentData > QueryDocumentSnapshot המכילה את הנתונים והמטא נתונים שלך.
אפשרויות אפשרויות Snapshot ה- SnapshotOptions מהקריאה הראשונית ל- data() .

החזרות:

AppModelType

FirestoreDataConverter.toFirestore()

נקרא על ידי Firestore SDK להמיר אובייקט דגם מותאם אישית מסוג AppModelType לאובייקט JavaScript רגיל (מתאים לכתיבה ישירות למסד הנתונים של Firestore) מסוג DbModelType . כדי להשתמש set() עם merge ו- mergeFields , toFirestore() חייב להיות מוגדר עם PartialWithFieldValue<AppModelType> .

הסוג WithFieldValue<T> מרחיב T כדי לאפשר גם להשתמש ב-FieldValues ​​כגון deleteField() כערכי מאפיינים.

חֲתִימָה:

toFirestore(modelObject: WithFieldValue<AppModelType>): WithFieldValue<DbModelType>;

פרמטרים

פָּרָמֶטֶר סוּג תיאור
modelObject WithFieldValue <AppModelType>

החזרות:

WithFieldValue <DbModelType>

FirestoreDataConverter.toFirestore()

נקרא על ידי Firestore SDK להמיר אובייקט דגם מותאם אישית מסוג AppModelType לאובייקט JavaScript רגיל (מתאים לכתיבה ישירות למסד הנתונים של Firestore) מסוג DbModelType . בשימוש עם setDoc() , ועם merge:true או mergeFields .

הסוג PartialWithFieldValue<T> מרחיב Partial<T> כדי לאפשר שימוש ב- FieldValues ​​כגון arrayUnion() כערכי מאפיינים. הוא תומך גם Partial מקונן על ידי מתן אפשרות להשמטת שדות מקוננים.

חֲתִימָה:

toFirestore(modelObject: PartialWithFieldValue<AppModelType>, options: SetOptions): PartialWithFieldValue<DbModelType>;

פרמטרים

פָּרָמֶטֶר סוּג תיאור
modelObject PartialWithFieldValue <AppModelType>
אפשרויות הגדר אפשרויות

החזרות:

PartialWithFieldValue <DbModelType>

דוגמא

דוגמה פשוטה

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);
}

דוגמה מתקדמת

// 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');
    }
}