FirestoreDataConverter interface

Конвертер, используемый withConverter() для преобразования пользовательских объектов типа AppModelType в данные Firestore типа DbModelType .

Использование конвертера позволяет указывать аргументы универсального типа при хранении и извлечении объектов из Firestore.

В этом контексте «AppModel» — это класс, который используется в приложении для упаковки связанной информации и функций. Такой класс может, например, иметь свойства со сложными вложенными типами данных, свойства, используемые для запоминания, свойства типов, не поддерживаемых Firestore (таких как symbol и bigint ) и вспомогательные функции, выполняющие составные операции. Такие классы не подходят и/или невозможны для хранения в базе данных Firestore. Вместо этого экземпляры таких классов необходимо преобразовать в «простые старые объекты JavaScript» (POJO) с исключительно примитивными свойствами, потенциально вложенными внутри других POJO или массивов POJO. В этом контексте этот тип называется «DbModel» и может быть объектом, подходящим для сохранения в Firestore. Для удобства приложения могут реализовать FirestoreDataConverter и зарегистрировать преобразователь с помощью объектов Firestore, таких как DocumentReference или Query , чтобы автоматически преобразовать AppModel в DbModel при сохранении в Firestore и преобразовать DbModel в AppModel при извлечении из Firestore.

Подпись:

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

Методы

Метод Описание
изFirestore(снимок) Вызывается Firestore SDK для преобразования данных Firestore в объект типа AppModelType . Вы можете получить доступ к своим данным, вызвав: snapshot.data() . Как правило, данные, возвращаемые из snapshot.data() могут быть преобразованы в DbModelType ; однако это не гарантируется, поскольку Firestore не применяет схему к базе данных. Например, запись из предыдущей версии приложения или запись из другого клиента, который не использовал преобразователь типов, могла записать данные с другими свойствами и/или типами свойств. Реализация должна будет выбрать, следует ли корректно восстановить несоответствующие данные или выдать ошибку.
toFirestore (модельОбъект) Вызывается Firestore SDK для преобразования пользовательского объекта модели типа AppModelType в простой объект JavaScript (подходящий для записи непосредственно в базу данных Firestore) типа DbModelType . Используется с setDoc(). , и . Тип WithFieldValue<T> расширяет T , позволяя также использовать FieldValues, такие как deleteField(), в качестве значений свойств.
toFirestore (modelObject, параметры) Вызывается 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() .

Как правило, данные, возвращаемые из snapshot.data() можно преобразовать в DbModelType ; однако это не гарантируется, поскольку Firestore не применяет схему к базе данных. Например, запись из предыдущей версии приложения или запись из другого клиента, который не использовал преобразователь типов, могла записать данные с другими свойствами и/или типами свойств. Реализация должна будет выбрать, следует ли корректно восстановить несоответствующие данные или выдать ошибку.

Подпись:

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

Параметры

Параметр Тип Описание
снимок Снимок документа запроса < Данные документа , Данные документа > QueryDocumentSnapshot содержащий ваши данные и метаданные.

Возврат:

AppModelType

FirestoreDataConverter.toFirestore()

Вызывается Firestore SDK для преобразования объекта пользовательской модели типа AppModelType в простой объект JavaScript (подходящий для записи непосредственно в базу данных Firestore) типа DbModelType . Используется с setDoc(). , и .

Тип WithFieldValue<T> расширяет T , позволяя также использовать FieldValues, такие как deleteField(), в качестве значений свойств.

Подпись:

toFirestore(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>;

Параметры

Параметр Тип Описание
модельОбъект Частичносфилдвалуе <типмодели приложения>
параметры Установить параметры

Возврат:

Частичносфилдвалуе <ТипМоделиДб>

Пример

Простой пример

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