Cloud Firestore รองรับการคงอยู่ของข้อมูลแบบออฟไลน์ คุณลักษณะนี้แคชสำเนาของข้อมูล Cloud Firestore ที่แอปของคุณกำลังใช้งาน ดังนั้นแอปของคุณจึงสามารถเข้าถึงข้อมูลได้เมื่ออุปกรณ์ออฟไลน์ คุณสามารถเขียน อ่าน ฟัง และสืบค้นข้อมูลที่แคชไว้ได้ เมื่ออุปกรณ์กลับมาออนไลน์ Cloud Firestore จะซิงโครไนซ์การเปลี่ยนแปลงในเครื่องที่ทำโดยแอปของคุณกับแบ็กเอนด์ Cloud Firestore
หากต้องการใช้การคงอยู่แบบออฟไลน์ คุณไม่จำเป็นต้องทำการเปลี่ยนแปลงใดๆ กับรหัสที่คุณใช้เพื่อเข้าถึงข้อมูล Cloud Firestore เมื่อเปิดใช้งานการคงอยู่แบบออฟไลน์ ไลบรารีไคลเอ็นต์ Cloud Firestore จะจัดการการเข้าถึงข้อมูลออนไลน์และออฟไลน์โดยอัตโนมัติ และซิงโครไนซ์ข้อมูลในเครื่องเมื่ออุปกรณ์กลับมาออนไลน์
กำหนดค่าการคงอยู่แบบออฟไลน์
เมื่อคุณเริ่มต้น Cloud Firestore คุณสามารถเปิดหรือปิดใช้งานการคงอยู่แบบออฟไลน์:
- สำหรับแพลตฟอร์ม Android และ Apple การคงอยู่แบบออฟไลน์จะเปิดใช้งานตามค่าเริ่มต้น หากต้องการปิดใช้งานการคงอยู่ ให้ตั้งค่าตัวเลือก
PersistenceEnabled
เป็นfalse
- สำหรับเว็บ การคงอยู่แบบออฟไลน์จะถูกปิดใช้งานตามค่าเริ่มต้น เมื่อต้องการเปิดใช้งานการคงอยู่ ให้เรียกใช้เมธอด
enablePersistence
แคชของ Cloud Firestore จะไม่ถูกล้างโดยอัตโนมัติระหว่างเซสชันต่างๆ ดังนั้น หากเว็บแอปของคุณจัดการข้อมูลที่ละเอียดอ่อน ตรวจสอบให้แน่ใจว่าได้ถามผู้ใช้ว่าพวกเขาใช้อุปกรณ์ที่เชื่อถือได้หรือไม่ ก่อนที่จะเปิดใช้งานการคงอยู่
Web version 9
// Memory cache is the default if no config is specified.
initializeFirestore(app);
// This is the default behavior if no persistence is specified.
initializeFirestore(app, {localCache: memoryLocalCache()});
// Defaults to single-tab persistence if no tab manager is specified.
initializeFirestore(app, {localCache: persistentLocalCache(/*settings*/{})});
// Same as `initializeFirestore(app, {localCache: persistentLocalCache(/*settings*/{})})`,
// but more explicit about tab management.
initializeFirestore(app,
{localCache:
persistentLocalCache(/*settings*/{tabManager: persistentSingleTabManager()})
});
// Use multi-tab IndexedDb persistence.
initializeFirestore(app,
{localCache:
persistentLocalCache(/*settings*/{tabManager: persistentMultipleTabManager()})
});
Web version 8
firebase.firestore().enablePersistence() .catch((err) => { if (err.code == 'failed-precondition') { // Multiple tabs open, persistence can only be enabled // in one tab at a a time. // ... } else if (err.code == 'unimplemented') { // The current browser does not support all of the // features required to enable persistence // ... } }); // Subsequent queries will use persistence, if it was enabled successfully
สวิฟต์
let settings = FirestoreSettings() // Use memory-only cache settings.cacheSettings = MemoryCacheSettings(garbageCollectorSettings: MemoryLRUGCSettings()) // Use persistent disk cache, with 1 MB cache size settings.cacheSettings = PersistentCacheSettings(sizeBytes: 1_000_000) // Any additional options // ... // Enable offline data persistence let db = Firestore.firestore() db.settings = settings
วัตถุประสงค์-C
FIRFirestoreSettings *settings = [[FIRFirestoreSettings alloc] init]; // Use memory-only cache settings.cacheSettings = [[FIRMemoryCacheSettings alloc] initWithGarbageCollectorSettings:[[FIRMemoryLRUGCSettings alloc] init]]; // Use persistent disk cache (default behavior) // This example uses 1 million bytes, or 1 MB. settings.cacheSettings = [[FIRPersistentCacheSettings alloc] initWithSizeBytes:@1000000]; // Any additional options // ... // Enable offline data persistence FIRFirestore *db = [FIRFirestore firestore]; db.settings = settings;
Kotlin+KTX
val settings = firestoreSettings { // Use memory cache setLocalCacheSettings(memoryCacheSettings {}) // Use persistent disk cache (default) setLocalCacheSettings(persistentCacheSettings {}) } db.firestoreSettings = settings
Java
FirebaseFirestoreSettings settings = new FirebaseFirestoreSettings.Builder(db.getFirestoreSettings()) // Use memory-only cache .setLocalCacheSettings(MemoryCacheSettings.newBuilder().build()) // Use persistent disk cache (default) .setLocalCacheSettings(PersistentCacheSettings.newBuilder() .build()) .build(); db.setFirestoreSettings(settings);
Dart
// Apple and Android db.settings = const Settings(persistenceEnabled: true); // Web await db .enablePersistence(const PersistenceSettings(synchronizeTabs: true));
กำหนดค่าขนาดแคช
เมื่อเปิดใช้งานการคงอยู่ Cloud Firestore จะแคชทุกเอกสารที่ได้รับจากแบ็กเอนด์สำหรับการเข้าถึงแบบออฟไลน์ Cloud Firestore กำหนดเกณฑ์เริ่มต้นสำหรับขนาดแคช หลังจากเกินค่าเริ่มต้น Cloud Firestore จะพยายามล้างเอกสารเก่าที่ไม่ได้ใช้เป็นระยะๆ คุณสามารถกำหนดค่าเกณฑ์ขนาดแคชอื่นหรือปิดใช้งานกระบวนการล้างข้อมูลทั้งหมด:
Web version 9
import { initializeFirestore, CACHE_SIZE_UNLIMITED } from "firebase/firestore"; const firestoreDb = initializeFirestore(app, { cacheSizeBytes: CACHE_SIZE_UNLIMITED });
Web version 8
firebase.firestore().settings({ cacheSizeBytes: firebase.firestore.CACHE_SIZE_UNLIMITED });
สวิฟต์
// The default cache size threshold is 100 MB. Configure "cacheSizeBytes" // for a different threshold (minimum 1 MB) or set to "FirestoreCacheSizeUnlimited" // to disable clean-up. let settings = Firestore.firestore().settings // Set cache size to 1 MB settings.cacheSettings = PersistentCacheSettings(sizeBytes: 1_000_000) Firestore.firestore().settings = settings
วัตถุประสงค์-C
// The default cache size threshold is 100 MB. Configure "cacheSizeBytes" // for a different threshold (minimum 1 MB) or set to "kFIRFirestoreCacheSizeUnlimited" // to disable clean-up. FIRFirestoreSettings *settings = [FIRFirestore firestore].settings; // Set cache size to 1 MB settings.cacheSettings = [[FIRPersistentCacheSettings alloc] initWithSizeBytes:@1000000]; [FIRFirestore firestore].settings = settings;
Kotlin+KTX
// The default cache size threshold is 100 MB. Configure "setCacheSizeBytes" // for a different threshold (minimum 1 MB) or set to "CACHE_SIZE_UNLIMITED" // to disable clean-up. val settings = FirebaseFirestoreSettings.Builder() .setCacheSizeBytes(FirebaseFirestoreSettings.CACHE_SIZE_UNLIMITED) .build() db.firestoreSettings = settings
Java
// The default cache size threshold is 100 MB. Configure "setCacheSizeBytes" // for a different threshold (minimum 1 MB) or set to "CACHE_SIZE_UNLIMITED" // to disable clean-up. FirebaseFirestoreSettings settings = new FirebaseFirestoreSettings.Builder() .setCacheSizeBytes(FirebaseFirestoreSettings.CACHE_SIZE_UNLIMITED) .build(); db.setFirestoreSettings(settings);
Dart
db.settings = const Settings( persistenceEnabled: true, cacheSizeBytes: Settings.CACHE_SIZE_UNLIMITED, );
ฟังข้อมูลออฟไลน์
ในขณะที่อุปกรณ์ออฟไลน์ หากคุณเปิดใช้งานการคงอยู่แบบออฟไลน์ ผู้ฟังของคุณจะได้รับกิจกรรมการฟังเมื่อข้อมูลที่แคชในเครื่องเปลี่ยนแปลง คุณสามารถฟังเอกสาร คอลเลกชัน และแบบสอบถาม
ในการตรวจสอบว่าคุณได้รับข้อมูลจากเซิร์ฟเวอร์หรือแคชหรือไม่ ให้ใช้คุณสมบัติ fromCache
บน SnapshotMetadata
ในเหตุการณ์สแน็ปช็อตของคุณ ถ้า fromCache
เป็น true
แสดงว่าข้อมูลมาจากแคช และอาจเก่าหรือไม่สมบูรณ์ หาก fromCache
เป็น false
แสดงว่าข้อมูลนั้นสมบูรณ์และเป็นปัจจุบันพร้อมการอัปเดตล่าสุดบนเซิร์ฟเวอร์
ตามค่าเริ่มต้น จะไม่มีเหตุการณ์เกิดขึ้นหากมีการเปลี่ยนแปลง SnapshotMetadata
เท่านั้น หากคุณใช้ค่า fromCache
ให้ระบุตัวเลือกการฟัง includeMetadataChanges
เมื่อคุณแนบตัวจัดการการฟังของคุณ
Web version 9
import { collection, onSnapshot, where, query } from "firebase/firestore"; const q = query(collection(db, "cities"), where("state", "==", "CA")); onSnapshot(q, { includeMetadataChanges: true }, (snapshot) => { snapshot.docChanges().forEach((change) => { if (change.type === "added") { console.log("New city: ", change.doc.data()); } const source = snapshot.metadata.fromCache ? "local cache" : "server"; console.log("Data came from " + source); }); });
Web version 8
db.collection("cities").where("state", "==", "CA") .onSnapshot({ includeMetadataChanges: true }, (snapshot) => { snapshot.docChanges().forEach((change) => { if (change.type === "added") { console.log("New city: ", change.doc.data()); } var source = snapshot.metadata.fromCache ? "local cache" : "server"; console.log("Data came from " + source); }); });
สวิฟต์
// Listen to metadata updates to receive a server snapshot even if // the data is the same as the cached data. db.collection("cities").whereField("state", isEqualTo: "CA") .addSnapshotListener(includeMetadataChanges: true) { querySnapshot, error in guard let snapshot = querySnapshot else { print("Error retreiving snapshot: \(error!)") return } for diff in snapshot.documentChanges { if diff.type == .added { print("New city: \(diff.document.data())") } } let source = snapshot.metadata.isFromCache ? "local cache" : "server" print("Metadata: Data fetched from \(source)") }
วัตถุประสงค์-C
// Listen to metadata updates to receive a server snapshot even if // the data is the same as the cached data. [[[db collectionWithPath:@"cities"] queryWhereField:@"state" isEqualTo:@"CA"] addSnapshotListenerWithIncludeMetadataChanges:YES listener:^(FIRQuerySnapshot *snapshot, NSError *error) { if (snapshot == nil) { NSLog(@"Error retreiving snapshot: %@", error); return; } for (FIRDocumentChange *diff in snapshot.documentChanges) { if (diff.type == FIRDocumentChangeTypeAdded) { NSLog(@"New city: %@", diff.document.data); } } NSString *source = snapshot.metadata.isFromCache ? @"local cache" : @"server"; NSLog(@"Metadata: Data fetched from %@", source); }];
Kotlin+KTX
db.collection("cities").whereEqualTo("state", "CA") .addSnapshotListener(MetadataChanges.INCLUDE) { querySnapshot, e -> if (e != null) { Log.w(TAG, "Listen error", e) return@addSnapshotListener } for (change in querySnapshot!!.documentChanges) { if (change.type == DocumentChange.Type.ADDED) { Log.d(TAG, "New city: ${change.document.data}") } val source = if (querySnapshot.metadata.isFromCache) { "local cache" } else { "server" } Log.d(TAG, "Data fetched from $source") } }
Java
db.collection("cities").whereEqualTo("state", "CA") .addSnapshotListener(MetadataChanges.INCLUDE, new EventListener<QuerySnapshot>() { @Override public void onEvent(@Nullable QuerySnapshot querySnapshot, @Nullable FirebaseFirestoreException e) { if (e != null) { Log.w(TAG, "Listen error", e); return; } for (DocumentChange change : querySnapshot.getDocumentChanges()) { if (change.getType() == Type.ADDED) { Log.d(TAG, "New city:" + change.getDocument().getData()); } String source = querySnapshot.getMetadata().isFromCache() ? "local cache" : "server"; Log.d(TAG, "Data fetched from " + source); } } });
Dart
db .collection("cities") .where("state", isEqualTo: "CA") .snapshots(includeMetadataChanges: true) .listen((querySnapshot) { for (var change in querySnapshot.docChanges) { if (change.type == DocumentChangeType.added) { final source = (querySnapshot.metadata.isFromCache) ? "local cache" : "server"; print("Data fetched from $source}"); } } });
รับข้อมูลออฟไลน์
หากคุณได้รับเอกสารขณะที่อุปกรณ์ออฟไลน์อยู่ Cloud Firestore จะส่งคืนข้อมูลจากแคช
เมื่อสอบถามคอลเลกชัน ผลลัพธ์ที่ว่างเปล่าจะถูกส่งกลับหากไม่มีเอกสารที่แคชไว้ เมื่อเรียกเอกสารเฉพาะ ข้อผิดพลาดจะถูกส่งกลับแทน
สอบถามข้อมูลออฟไลน์
การสืบค้นทำงานด้วยความคงอยู่แบบออฟไลน์ คุณสามารถดึงผลลัพธ์ของการค้นหาด้วยการรับโดยตรงหรือการฟัง ตามที่อธิบายไว้ในส่วนก่อนหน้า คุณยังสามารถสร้างการสืบค้นข้อมูลใหม่บนข้อมูลที่คงอยู่ในเครื่องในขณะที่อุปกรณ์ออฟไลน์ได้ แต่การสืบค้นจะเริ่มต้นเฉพาะกับเอกสารที่แคชไว้เท่านั้น
กำหนดค่าดัชนีแบบสอบถามออฟไลน์
ตามค่าเริ่มต้น Firestore SDK จะสแกนเอกสารทั้งหมดในคอลเล็กชันในแคชในเครื่องเมื่อดำเนินการค้นหาแบบออฟไลน์ ด้วยลักษณะการทำงานเริ่มต้นนี้ ประสิทธิภาพการสืบค้นแบบออฟไลน์อาจประสบเมื่อผู้ใช้ออฟไลน์เป็นระยะเวลานาน
คุณสามารถปรับปรุงประสิทธิภาพการสืบค้นแบบออฟไลน์ได้โดยกำหนดค่าดัชนีการสืบค้นภายในเครื่อง:
สวิฟต์
SDK แพลตฟอร์ม Apple มีเมธอด setIndexConfiguration
ที่อ่านการกำหนดค่าที่มีโครงสร้าง JSON เดียวกันกับที่ใช้กำหนดค่าดัชนีบนเซิร์ฟเวอร์ ตาม รูปแบบข้อกำหนดดัชนี เดียวกัน
// You will normally read this from a file asset or cloud storage. let indexConfigJson = """ { indexes: [ ... ], fieldOverrides: [ ... ] } """ // Apply the configuration. Firestore.firestore().setIndexConfiguration(indexConfigJson)
วัตถุประสงค์-C
SDK แพลตฟอร์ม Apple มีเมธอด setIndexConfiguration
ที่อ่านการกำหนดค่าที่มีโครงสร้าง JSON เดียวกับที่ใช้กำหนดค่าดัชนีบนเซิร์ฟเวอร์ ตาม รูปแบบข้อกำหนดดัชนี เดียวกัน
// You will normally read this from a file asset or cloud storage. NSString *indexConfigJson = @" { " " indexes: [ " " ... " " ], " " fieldOverrides: [ " " ... " " ] " " } "; // Apply the configuration. [[FIRFirestore firestore] setIndexConfigurationFromJSON:indexConfigJson completion:^(NSError * _Nullable error) { // ... }];
Java
Android SDK มีเมธอด setIndexConfiguration
ที่อ่านการกำหนดค่าที่มีโครงสร้าง JSON เดียวกับที่ใช้กำหนดค่าดัชนีบนเซิร์ฟเวอร์ ตาม รูปแบบข้อกำหนดดัชนี เดียวกัน
// You will normally read this from a file asset or cloud storage. String indexConfigJson = " { " + " indexes: [ " + " ... " + " ], " + " fieldOverrides: [ " + " ... " + " ] " + " } "; // Apply the configuration. FirebaseFirestore.getInstance().setIndexConfiguration(indexConfigJson);
Kotlin+KTX
Android SDK มีเมธอด setIndexConfiguration
ที่อ่านการกำหนดค่าที่มีโครงสร้าง JSON เดียวกับที่ใช้กำหนดค่าดัชนีบนเซิร์ฟเวอร์ ตาม รูปแบบข้อกำหนดดัชนี เดียวกัน
// You will normally read this from a file asset or cloud storage. val indexConfigJson = """ { indexes: [ ... ], fieldOverrides: [ ... ] } """ // Apply the configuration. FirebaseFirestore.getInstance().setIndexConfiguration(indexConfigJson)
Dart
Flutter SDK มีเมธอด setIndexConfigurationFromJSON
ที่อ่านการกำหนดค่าที่มีโครงสร้าง JSON เดียวกันกับที่ใช้กำหนดค่าดัชนีบนเซิร์ฟเวอร์ ตาม รูปแบบการกำหนดดัชนี เดียวกัน
// You will normally read this from a file asset or cloud storage. var indexConfigJson = """ { indexes: [ ... ], fieldOverrides: [ ... ] } """; // Apply the configuration. await FirebaseFirestore.instance.setIndexConfigurationFromJSON(json: indexConfigJson);
หรืออีกทางหนึ่ง คุณสามารถใช้เมธอด setIndexConfiguration
เพื่อกำหนดค่าดัชนีด้วย API ที่อิงตามคลาส
var indexes = [ Index( collectionGroup: "posts", queryScope: QueryScope.collection, fields: [ IndexField(fieldPath: "author", arrayConfig: ArrayConfig.contains), IndexField(fieldPath: "timestamp", order: Order.descending) ], ), ]; await FirebaseFirestore.instance.setIndexConfiguration(indexes: indexes);
การกำหนดค่าดัชนีออฟไลน์ที่จะใช้ขึ้นอยู่กับคอลเล็กชันและเอกสารที่แอปของคุณเข้าถึงมากขณะออฟไลน์และประสิทธิภาพออฟไลน์ที่คุณต้องการ แม้ว่าคุณจะสามารถส่งออกการกำหนดค่าดัชนีแบ็กเอนด์เพื่อใช้ในไคลเอนต์ได้ แต่รูปแบบการเข้าถึงแบบออฟไลน์ของแอปอาจแตกต่างอย่างมากจากรูปแบบการเข้าถึงแบบออนไลน์ ดังนั้นการกำหนดค่าดัชนีแบบออนไลน์ของคุณอาจไม่เหมาะสำหรับการใช้งานแบบออฟไลน์ คอลเลกชันและเอกสารใดที่คุณต้องการให้แอปของคุณเข้าถึงแบบออฟไลน์ด้วยประสิทธิภาพสูง เมื่อคุณวิเคราะห์พฤติกรรมของแอปแล้ว ให้ปฏิบัติตามหลักการสำหรับการกำหนดดัชนีจาก คู่มือการจัดทำดัชนี
ในการทำให้การกำหนดค่าดัชนีออฟไลน์พร้อมสำหรับการโหลดในแอปไคลเอ็นต์ของคุณ:
- รวบรวมและเผยแพร่ด้วยแอปของคุณ
- ดาวน์โหลดได้จาก CDN
- ดึงข้อมูลจากระบบจัดเก็บข้อมูล เช่น Cloud Storage สำหรับ Firebase
ปิดใช้งานและเปิดใช้งานการเข้าถึงเครือข่าย
คุณสามารถใช้วิธีการด้านล่างเพื่อปิดการเข้าถึงเครือข่ายสำหรับไคลเอ็นต์ Cloud Firestore ของคุณ ในขณะที่การเข้าถึงเครือข่ายถูกปิดใช้งาน ผู้ฟังสแน็ปช็อตและคำขอเอกสารทั้งหมดจะดึงผลลัพธ์จากแคช การดำเนินการเขียนอยู่ในคิวจนกว่าจะเปิดใช้งานการเข้าถึงเครือข่ายอีกครั้ง
Web version 9
import { disableNetwork } from "firebase/firestore"; await disableNetwork(db); console.log("Network disabled!"); // Do offline actions // ...
Web version 8
firebase.firestore().disableNetwork() .then(() => { // Do offline actions // ... });
สวิฟต์
Firestore.firestore().disableNetwork { (error) in // Do offline things // ... }
วัตถุประสงค์-C
[[FIRFirestore firestore] disableNetworkWithCompletion:^(NSError *_Nullable error) { // Do offline actions // ... }];
Kotlin+KTX
db.disableNetwork().addOnCompleteListener { // Do offline things // ... }
Java
db.disableNetwork() .addOnCompleteListener(new OnCompleteListener<Void>() { @Override public void onComplete(@NonNull Task<Void> task) { // Do offline things // ... } });
Dart
db.disableNetwork().then((_) { // Do offline things });
ใช้วิธีการต่อไปนี้เพื่อเปิดใช้งานการเข้าถึงเครือข่ายอีกครั้ง:
Web version 9
import { enableNetwork } from "firebase/firestore"; await enableNetwork(db); // Do online actions // ...
Web version 8
firebase.firestore().enableNetwork() .then(() => { // Do online actions // ... });
สวิฟต์
Firestore.firestore().enableNetwork { (error) in // Do online things // ... }
วัตถุประสงค์-C
[[FIRFirestore firestore] enableNetworkWithCompletion:^(NSError *_Nullable error) { // Do online actions // ... }];
Kotlin+KTX
db.enableNetwork().addOnCompleteListener { // Do online things // ... }
Java
db.enableNetwork() .addOnCompleteListener(new OnCompleteListener<Void>() { @Override public void onComplete(@NonNull Task<Void> task) { // Do online things // ... } });
Dart
db.enableNetwork().then((_) { // Back online });