FirestoreDataConverter interface

AppModelType türündeki kullanıcı nesnelerini DbModelType türündeki Firestore verilerine dönüştürmek için withConverter() tarafından kullanılan dönüştürücü .

Dönüştürücüyü kullanmak, nesneleri Firestore'dan saklarken ve alırken genel tür bağımsız değişkenlerini belirtmenize olanak tanır.

Bu bağlamda "AppModel", bir uygulamada ilgili bilgi ve işlevleri bir araya paketlemek için kullanılan bir sınıftır. Böyle bir sınıf, örneğin karmaşık, iç içe geçmiş veri türlerine sahip özelliklere, not alma için kullanılan özelliklere, Firestore tarafından desteklenmeyen türlerin özelliklerine ( symbol ve bigint gibi) sahip olabilir. ) ve bileşik işlemleri gerçekleştiren yardımcı işlevler. Bu tür sınıfların bir Firestore veritabanında saklanması uygun değildir ve/veya mümkün değildir. Bunun yerine, bu tür sınıfların örneklerinin, potansiyel olarak diğer POJO'ların veya POJO dizilerinin içine yerleştirilmiş, yalnızca ilkel özelliklere sahip "düz eski JavaScript nesnelerine" (POJO'lar) dönüştürülmesi gerekir. Bu bağlamda bu tür "DbModel" olarak anılır ve Firestore'da kalıcı olmaya uygun bir nesne olacaktır. Kolaylık sağlamak için uygulamalar FirestoreDataConverter uygulayabilir ve dönüştürücüyü DocumentReference veya Query gibi Firestore nesnelerine kaydedebilir , Firestore'da depolarken AppModel otomatik olarak DbModel dönüştürmek ve Firestore'dan alırken DbModel AppModel dönüştürmek için.

İmza:

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

Yöntemler

Yöntem Tanım
fromFirestore(anlık görüntü, seçenekler) Firestore verilerini AppModelType türünde bir nesneye dönüştürmek için Firestore SDK'sı tarafından çağrılır. Verilerinize şu numarayı arayarak erişebilirsiniz: snapshot.data(options) . Genellikle snapshot.data() işlevinden döndürülen veriler DbModelType öğesine aktarılabilir; ancak Firestore veritabanında bir şema uygulamadığından bu garanti edilmez. Örneğin, uygulamanın önceki bir sürümünden yapılan yazma işlemleri veya tür dönüştürücü kullanmayan başka bir istemciden yapılan yazma işlemleri, farklı özelliklere ve/veya özellik türlerine sahip yazılı verilere sahip olabilir. Uygulamanın, uygun olmayan verilerden hassas bir şekilde kurtarma mı yapacağını yoksa bir hata mı atacağını seçmesi gerekecektir. Bu yöntemi geçersiz kılmak için bkz.
toFirestore(modelObject) AppModelType türündeki özel bir model nesnesini DbModelType türündeki düz bir JavaScript nesnesine (doğrudan Firestore veritabanına yazmaya uygun) dönüştürmek için Firestore SDK tarafından çağrılır. set() merge ve mergeFields ile kullanmak için toFirestore() PartialWithFieldValue<AppModelType> ile tanımlanması gerekir. WithFieldValue<T> türü, T deleteField() gibi FieldValues'ların özellik değerleri olarak kullanılmasına da izin verecek şekilde genişletir.
toFirestore(modelObject, seçenekler) AppModelType türündeki özel bir model nesnesini DbModelType türündeki düz bir JavaScript nesnesine (doğrudan Firestore veritabanına yazmaya uygun) dönüştürmek için Firestore SDK tarafından çağrılır. setDoc() ile kullanılır ve merge:true veya mergeFields ile. PartialWithFieldValue<T> türü, Partial<T> , arrayUnion() gibi FieldValues'ların özellik değerleri olarak kullanılmasına izin verecek şekilde genişletir. Ayrıca, iç içe geçmiş alanların atlanmasına izin vererek iç içe Partial de destekler.

FirestoreDataConverter.fromFirestore()

Firestore SDK'sı tarafından Firestore verilerini AppModelType türünde bir nesneye dönüştürmek için çağrılır . Verilerinize şu numarayı arayarak erişebilirsiniz: snapshot.data(options) .

Genellikle snapshot.data() dan döndürülen veriler DbModelType aktarılabilir. ; ancak Firestore veritabanında bir şema uygulamadığından bu garanti edilmez. Örneğin, uygulamanın önceki bir sürümünden yapılan yazma işlemleri veya tür dönüştürücü kullanmayan başka bir istemciden yapılan yazma işlemleri, farklı özelliklere ve/veya özellik türlerine sahip yazılı verilere sahip olabilir. Uygulamanın, uygun olmayan verilerden hassas bir şekilde kurtarma mı yapacağını yoksa bir hata mı atacağını seçmesi gerekecektir.

Bu yöntemi geçersiz kılmak için bkz.

İmza:

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

Parametreler

Parametre Tip Tanım
enstantane fotoğraf SorguBelge Anlık Görüntüsü < BelgeVerileri , BelgeVerileri > Verilerinizi ve meta verilerinizi içeren bir QueryDocumentSnapshot .
seçenekler Anlık Görüntü Seçenekleri data() ya yapılan ilk çağrıdaki SnapshotOptions .

İadeler:

UygulamaModel Türü

FirestoreDataConverter.toFirestore()

AppModelType türündeki özel bir model nesnesini DbModelType türündeki düz bir JavaScript nesnesine (doğrudan Firestore veritabanına yazmaya uygun) dönüştürmek için Firestore SDK tarafından çağrılır . set() merge ve mergeFields ile kullanmak için toFirestore() , PartialWithFieldValue<AppModelType> ile tanımlanmalıdır. .

WithFieldValue<T> türü, T deleteField() gibi FieldValues'ların özellik değerleri olarak kullanılmasına da izin verecek şekilde genişletir.

İmza:

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

Parametreler

Parametre Tip Tanım
modelNesne Alan Değeri ile <UygulamaModel Türü>

İadeler:

Alan Değeri ile <DbModelType>

FirestoreDataConverter.toFirestore()

AppModelType türündeki özel bir model nesnesini DbModelType türündeki düz bir JavaScript nesnesine (doğrudan Firestore veritabanına yazmaya uygun) dönüştürmek için Firestore SDK tarafından çağrılır . setDoc() ile kullanılır , ve merge:true veya mergeFields ile .

PartialWithFieldValue<T> türü, Partial<T> , arrayUnion() gibi FieldValues'ların özellik değerleri olarak kullanılmasına izin verecek şekilde genişletir. Ayrıca, iç içe geçmiş alanların atlanmasına izin vererek iç içe Partial de destekler.

İmza:

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

Parametreler

Parametre Tip Tanım
modelNesne Kısmi WithFieldValue <UygulamaModel Türü>
seçenekler Seçenekleri Ayarla

İadeler:

Kısmi WithFieldValue <DbModelType>

Örnek

Basit Örnek

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

Gelişmiş Örnek

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