FirestoreDataConverter interface

مبدلی که توسط withConverter() برای تبدیل اشیاء کاربر از نوع AppModelType به داده های Firestore از نوع DbModelType استفاده می شود. .

استفاده از مبدل به شما امکان می دهد تا آرگومان های نوع عمومی را هنگام ذخیره و بازیابی اشیاء از Firestore مشخص کنید.

در این زمینه، "AppModel" کلاسی است که در یک برنامه کاربردی برای بسته بندی اطلاعات و عملکردهای مرتبط با هم استفاده می شود. برای مثال، چنین کلاسی می‌تواند دارای ویژگی‌هایی با انواع داده‌های پیچیده و تودرتو، ویژگی‌های مورد استفاده برای حافظه‌گذاری، ویژگی‌های انواعی باشد که توسط Firestore پشتیبانی نمی‌شوند (مانند symbol و bigint . و توابع کمکی که عملیات ترکیبی را انجام می دهند. چنین کلاس هایی برای ذخیره در پایگاه داده Firestore مناسب و/یا امکان پذیر نیستند. درعوض، نمونه‌هایی از چنین کلاس‌هایی باید به «اشیاء جاوا اسکریپت قدیمی ساده» (POJOs) با ویژگی‌های منحصراً ابتدایی تبدیل شوند که به طور بالقوه در داخل سایر POJO یا آرایه‌های POJO قرار دارند. در این زمینه، این نوع به عنوان "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 به یک شی جاوا اسکریپت ساده (مناسب برای نوشتن مستقیم در پایگاه داده Firestore) از نوع DbModelType فراخوانی شده است. برای استفاده از set() با merge و mergeFields ، toFirestore() باید با PartialWithFieldValue<AppModelType> تعریف شود. نوع WithFieldValue<T> T را گسترش می دهد تا همچنین اجازه دهد FieldValue مانند deleteField() به عنوان مقادیر ویژگی استفاده شود.
toFirestore (modelObject، گزینه‌ها) توسط Firestore SDK برای تبدیل یک شی مدل سفارشی از نوع AppModelType به یک شی جاوا اسکریپت ساده (مناسب برای نوشتن مستقیم در پایگاه داده 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 حاوی داده‌ها و ابرداده‌های شما.
گزینه ها SnapshotOptions SnapshotOptions از فراخوانی اولیه به data() .

برمی‌گرداند:

AppModelType

FirestoreDataConverter.toFirestore()

فراخوانی شده توسط Firestore SDK برای تبدیل یک شی مدل سفارشی از نوع AppModelType به یک شی جاوا اسکریپت ساده (مناسب برای نوشتن مستقیم در پایگاه داده Firestore) از نوع DbModelType . برای استفاده از set() با merge و mergeFields ، toFirestore() باید با PartialWithFieldValue<AppModelType> تعریف شود .

نوع WithFieldValue<T> T را گسترش می دهد تا همچنین اجازه دهد FieldValue مانند deleteField() به عنوان مقادیر ویژگی استفاده شود.

امضا:

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

مولفه های

پارامتر تایپ کنید شرح
مدل شی WithFieldValue <AppModelType>

برمی‌گرداند:

WithFieldValue <DbModelType>

FirestoreDataConverter.toFirestore()

توسط Firestore SDK برای تبدیل یک شی مدل سفارشی از نوع AppModelType به یک شیء جاوا اسکریپت ساده (مناسب برای نوشتن مستقیم در پایگاه داده Firestore) از نوع DbModelType فراخوانی شده است. . استفاده شده با setDoc() و با merge:true یا mergeFields .

نوع PartialWithFieldValue<T> Partial<T> را گسترش می دهد تا اجازه دهد FieldValues ​​مانند arrayUnion() به عنوان مقادیر ویژگی استفاده شود. همچنین با اجازه دادن به حذف فیلدهای تودرتو از تودرتو Partial پشتیبانی می کند.

امضا:

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

مولفه های

پارامتر تایپ کنید شرح
مدل شی PartialWithFieldValue <AppModelType>
گزینه ها SetOptions

برمی‌گرداند:

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