ตัวแปลงที่ใช้โดย 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 < เอกสารข้อมูล , เอกสารข้อมูล > | QueryDocumentSnapshot ที่มีข้อมูลและข้อมูลเมตาของคุณ |
ผลตอบแทน:
AppModelType
FirestoreDataConverter.toFirestore()
เรียกโดย Firestore SDK เพื่อแปลงวัตถุโมเดลที่กำหนดเองประเภท AppModelType
เป็นวัตถุ Javascript ธรรมดา (เหมาะสำหรับการเขียนโดยตรงไปยังฐานข้อมูล Firestore) ประเภท DbModelType
. ใช้กับ setDoc() , และ .
ประเภท WithFieldValue<T>
จะขยาย T
เพื่ออนุญาตให้ใช้ FieldValues เช่น DeleteField() เป็นค่าคุณสมบัติด้วย
ลายเซ็น:
toFirestore(modelObject: WithFieldValue<AppModelType>): WithFieldValue<DbModelType>;
พารามิเตอร์
พารามิเตอร์ | พิมพ์ | คำอธิบาย |
---|---|---|
โมเดลวัตถุ | ด้วยค่าฟิลด์ <AppModelType> |
ผลตอบแทน:
ด้วยค่าฟิลด์ <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>;
พารามิเตอร์
พารามิเตอร์ | พิมพ์ | คำอธิบาย |
---|---|---|
โมเดลวัตถุ | บางส่วนด้วยFieldValue <AppModelType> | |
ตัวเลือก | ตั้งค่าตัวเลือก |
ผลตอบแทน:
บางส่วนด้วยFieldValue <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');
}
}