Popular Searches
Popular Course Categories
Popular Courses

Cloud Firestore

Firebase with Flutter

Cloud Firestore in Flutter


Cloud Firestore is a flexible, scalable NoSQL cloud database provided by Firebase. It stores application data in collections and documents and allows Flutter applications to create, read, update, delete, query, and listen to data in real time.


Cloud Firestore can be used for applications such as user profiles, products, orders, chat applications, task management systems, social applications, blogs, booking systems, and dashboards. It supports real-time updates, expressive queries, hierarchical data structures, and offline capabilities. Firebase Cloud Firestore Documentation




1. What is Cloud Firestore?


Cloud Firestore is a NoSQL document database designed for mobile, web, and server applications. Instead of storing data in traditional rows and columns, Firestore stores data inside documents that are organized into collections.


For example, a user collection may contain multiple user documents:


users
├── user001
├── user002
├── user003
└── user004

Each document can contain fields such as name, email, age, phone number, and other application-specific information.




2. Firestore Data Model


The basic structure of Cloud Firestore is:


Firestore
   |
   +-- Collection
         |
         +-- Document
               |
               +-- Fields
               |
               +-- Subcollection

Example


users
  |
  +-- user123
       |
       +-- name: "John"
       +-- email: "[email protected]"
       +-- age: 25
       |
       +-- orders
             |
             +-- order001
             +-- order002



3. Collection


A collection is a group of related documents.


For example:


users
products
orders
messages
courses

A collection does not normally store application data directly as fields. Instead, it contains documents.




4. Document


A document is a record containing fields and values.


Example:


{
  "name": "John Doe",
  "email": "[email protected]",
  "age": 25,
  "isActive": true
}

A document has a unique document ID within its collection.




5. Fields


Fields contain the actual values stored inside a document.










Field Example Value Type
name John Doe String
age 25 Number
isActive true Boolean
skills ["Flutter","Dart"] Array
address {city: "Mumbai"} Map
createdAt Timestamp Timestamp



6. Subcollections


A document can contain subcollections. Subcollections are useful when data logically belongs to a particular document.


For example:


users
  |
  +-- user123
       |
       +-- name: "John"
       +-- email: "[email protected]"
       |
       +-- orders
            |
            +-- order001
            +-- order002

Here, orders is a subcollection inside the user123 document.




7. Why Use Cloud Firestore with Flutter?



  • Cloud-hosted NoSQL database.

  • Easy integration with Flutter through the Firebase FlutterFire plugin.

  • Supports real-time data updates.

  • Supports one-time data reads.

  • Supports filtering and sorting.

  • Supports hierarchical collections and subcollections.

  • Provides offline data support on supported platforms.

  • Integrates with Firebase Authentication.

  • Can be protected with Firebase Security Rules.

  • Suitable for small applications and applications that need to scale.


Firestore supports flexible data structures, expressive queries, real-time listeners, and offline capabilities. Learn more about Cloud Firestore




8. Prerequisites


Before using Cloud Firestore in Flutter, you should have:



  • Flutter SDK installed.

  • A Flutter project.

  • A Firebase project.

  • Firebase configured with the Flutter application.

  • The Cloud Firestore database created in Firebase Console.


For current Firebase Flutter setup instructions, see Get Started with Firebase in Flutter.




9. Add Cloud Firestore to Flutter


From the Flutter project directory, run:


flutter pub add cloud_firestore

After adding a Firebase Flutter plugin, Firebase's current setup flow uses flutterfire configure to keep the application's Firebase configuration up to date. Firebase Flutter Setup




10. Import Cloud Firestore


import 'package:cloud_firestore/cloud_firestore.dart';



11. Get Firestore Instance


The main Firestore instance can be accessed using FirebaseFirestore.instance.


final FirebaseFirestore db = FirebaseFirestore.instance;

You can also directly use:


FirebaseFirestore.instance



12. Initialize Firebase


Firebase should be initialized before using Firestore.


void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  await Firebase.initializeApp();


  runApp(const MyApp());
}


In a typical FlutterFire project, Firebase initialization uses the generated firebase_options.dart configuration.


await Firebase.initializeApp(
  options: DefaultFirebaseOptions.currentPlatform,
);



13. Create a Firestore Database



  1. Open Firebase Console.

  1. Select your Firebase project.

  1. Open Firestore Database.

  1. Create a database.

  1. Choose the appropriate database configuration and location.

  1. Configure Security Rules according to your application's requirements.


Firestore data can also be managed directly from the Firebase Console. Manage Cloud Firestore with Firebase Console




14. Add Data to Firestore


There are several ways to add data to Firestore. You can specify a document ID yourself or allow Firestore to generate one automatically. Add Data to Cloud Firestore




15. Add Document with Auto-Generated ID


The add() method creates a new document and automatically generates its document ID.


await FirebaseFirestore.instance
    .collection('users')
    .add({
  'name': 'John Doe',
  'email': '[email protected]',
  'age': 25,
});

The resulting structure may look like:


users
  |
  +-- automatically-generated-id
       |
       +-- name: John Doe
       +-- email: [email protected]
       +-- age: 25



16. Add Document with Custom ID


Use doc() when you want to specify the document ID.


await FirebaseFirestore.instance
    .collection('users')
    .doc('user001')
    .set({
  'name': 'John Doe',
  'email': '[email protected]',
  'age': 25,
});

The document ID in this example is user001.




17. Set Data


The set() method writes data to a document.


final userRef = FirebaseFirestore.instance
    .collection('users')
    .doc('user001');

await userRef.set({
  'name': 'John Doe',
  'email': '[email protected]',
});




18. Set Data with Merge


When you want to update selected fields without replacing the complete document, you can use merge behavior.


await FirebaseFirestore.instance
    .collection('users')
    .doc('user001')
    .set({
  'age': 26,
}, SetOptions(merge: true));

This keeps other existing fields in the document while updating the specified field.




19. Firestore Data Types


Firestore supports several common data types, including strings, booleans, numbers, arrays, maps, timestamps, null values, document references, and other supported types.


final data = {
  'name': 'John',
  'age': 25,
  'isStudent': false,
  'skills': ['Flutter', 'Dart'],
  'address': {
    'city': 'Mumbai',
    'country': 'India',
  },
  'createdAt': Timestamp.now(),
  'description': null,
};



20. Read a Single Document


Use get() to retrieve a document once.


final doc = await FirebaseFirestore.instance
    .collection('users')
    .doc('user001')
    .get();

if (doc.exists) {
  print(doc.data());
}


Firestore supports one-time reads as well as real-time listeners. Get Data with Cloud Firestore




21. Access Document Data


final doc = await FirebaseFirestore.instance
    .collection('users')
    .doc('user001')
    .get();

final data = doc.data();


if (data != null) {
  print(data['name']);
  print(data['email']);
  print(data['age']);
}




22. Check Whether a Document Exists


final doc = await FirebaseFirestore.instance
    .collection('users')
    .doc('user001')
    .get();

if (doc.exists) {
  print('Document exists');
} else {
  print('Document does not exist');
}




23. Read All Documents from a Collection


Use a collection reference and get() to retrieve documents from a collection.


final snapshot = await FirebaseFirestore.instance
    .collection('users')
    .get();

for (final doc in snapshot.docs) {
  print(doc.id);
  print(doc.data());
}




24. Get Document ID


Each Firestore document has an ID that can be accessed through doc.id.


for (final doc in snapshot.docs) {
  print('Document ID: ${doc.id}');
}



25. Convert Firestore Data into a List


final snapshot = await FirebaseFirestore.instance
    .collection('users')
    .get();

final users = snapshot.docs.map((doc) {
  return {
    'id': doc.id,
    ...doc.data(),
  };
}).toList();




26. Display Firestore Data with FutureBuilder


FutureBuilder is useful for displaying data obtained through a one-time Firestore request.


FutureBuilder(
  future: FirebaseFirestore.instance
      .collection('users')
      .get(),
  builder: (context, snapshot) {
    if (snapshot.connectionState == ConnectionState.waiting) {
      return const Center(
        child: CircularProgressIndicator(),
      );
    }

    if (snapshot.hasError) {
      return const Center(
        child: Text('Something went wrong'),
      );
    }


    if (!snapshot.hasData || snapshot.data!.docs.isEmpty) {
      return const Center(
        child: Text('No users found'),
      );
    }


    final users = snapshot.data!.docs;


    return ListView.builder(
      itemCount: users.length,
      itemBuilder: (context, index) {
        final user = users[index].data();


        return ListTile(
          title: Text(user['name'] ?? ''),
          subtitle: Text(user['email'] ?? ''),
        );
      },
    );
  },
)




27. Real-Time Firestore Data


Firestore supports real-time listeners. A listener receives an initial snapshot and then receives updates when the listened-to data changes.


FirebaseFirestore.instance
    .collection('users')
    .snapshots()
    .listen((snapshot) {
  for (final doc in snapshot.docs) {
    print(doc.data());
  }
});

Real-time listeners are useful for chat applications, live dashboards, notifications, collaborative applications, and other interfaces where data can change while the screen is open.




28. StreamBuilder with Firestore


StreamBuilder can be used to automatically rebuild the UI when Firestore data changes.


StreamBuilder>>(
  stream: FirebaseFirestore.instance
      .collection('users')
      .snapshots(),
  builder: (context, snapshot) {
    if (snapshot.connectionState == ConnectionState.waiting) {
      return const Center(
        child: CircularProgressIndicator(),
      );
    }

    if (snapshot.hasError) {
      return const Center(
        child: Text('Error loading users'),
      );
    }


    final users = snapshot.data?.docs ?? [];


    if (users.isEmpty) {
      return const Center(
        child: Text('No users found'),
      );
    }


    return ListView.builder(
      itemCount: users.length,
      itemBuilder: (context, index) {
        final user = users[index].data();


        return ListTile(
          title: Text(user['name'] ?? ''),
          subtitle: Text(user['email'] ?? ''),
        );
      },
    );
  },
)




29. Update Firestore Data


The update() method changes selected fields in an existing document.


await FirebaseFirestore.instance
    .collection('users')
    .doc('user001')
    .update({
  'age': 26,
  'isActive': true,
});



30. Update a Single Field


await FirebaseFirestore.instance
    .collection('users')
    .doc('user001')
    .update({
  'name': 'John Smith',
});



31. Delete a Document


Use delete() to remove a document.


await FirebaseFirestore.instance
    .collection('users')
    .doc('user001')
    .delete();



32. Delete a Field


You can remove a field from a document using FieldValue.delete().


await FirebaseFirestore.instance
    .collection('users')
    .doc('user001')
    .update({
  'temporaryField': FieldValue.delete(),
});



33. Firestore CRUD Operations


CRUD stands for Create, Read, Update, and Delete.








Operation Firestore Method
Create add() / set()
Read get() / snapshots()
Update update()
Delete delete()



34. Query Firestore Data


Firestore queries allow you to retrieve only documents matching particular conditions. Queries can be combined with filtering, sorting, limits, and other supported query features. Cloud Firestore Query Documentation




35. Query Using where()


The where() method can filter documents based on field values.


final snapshot = await FirebaseFirestore.instance
    .collection('users')
    .where('age', isGreaterThan: 18)
    .get();

for (final doc in snapshot.docs) {
  print(doc.data());
}




36. Equality Query


final snapshot = await FirebaseFirestore.instance
    .collection('users')
    .where('city', isEqualTo: 'Mumbai')
    .get();



37. Multiple Query Conditions


Firestore supports compound queries when the selected fields and query structure are supported.


final snapshot = await FirebaseFirestore.instance
    .collection('users')
    .where('isActive', isEqualTo: true)
    .where('age', isGreaterThan: 18)
    .get();

Some compound queries may require an index. If Firestore requires an index, the error response can provide a link to create the required index.




38. Sorting Data with orderBy()


Use orderBy() to sort query results.


final snapshot = await FirebaseFirestore.instance
    .collection('users')
    .orderBy('name')
    .get();

Descending Order


final snapshot = await FirebaseFirestore.instance
    .collection('users')
    .orderBy('name', descending: true)
    .get();



39. Limit Query Results


Use limit() when you only need a specific number of documents.


final snapshot = await FirebaseFirestore.instance
    .collection('users')
    .limit(10)
    .get();

Limiting results can be useful for dashboards, previews, pagination, and performance-conscious screens.




40. Query with Multiple Conditions and Sorting


final snapshot = await FirebaseFirestore.instance
    .collection('products')
    .where('category', isEqualTo: 'Mobile')
    .where('price', isLessThan: 50000)
    .orderBy('price')
    .get();

Query structure must follow Firestore's query constraints and indexing requirements.




41. Query Using whereIn


Some queries can match a field against multiple values using supported operators such as whereIn.


final snapshot = await FirebaseFirestore.instance
    .collection('users')
    .where(
      'role',
      whereIn: ['admin', 'manager'],
    )
    .get();



42. Array Queries


For fields containing arrays, Firestore supports operators such as arrayContains.


final snapshot = await FirebaseFirestore.instance
    .collection('courses')
    .where(
      'skills',
      arrayContains: 'Flutter',
    )
    .get();



43. Search Example


A Firestore query can be used to filter data according to supported query operations.


final snapshot = await FirebaseFirestore.instance
    .collection('products')
    .where(
      'category',
      isEqualTo: 'Laptop',
    )
    .get();

For advanced full-text search requirements, a dedicated search solution may be more appropriate than relying on simple Firestore field filtering.




44. Firestore with Firebase Authentication


Cloud Firestore is commonly used together with Firebase Authentication. Authentication identifies the user, while Firestore stores application data associated with that user.


Example:


Authentication
      |
      v
Firebase User UID
      |
      v
Firestore
      |
      v
users/{uid}

Example


final user = FirebaseAuth.instance.currentUser;

if (user != null) {
  await FirebaseFirestore.instance
      .collection('users')
      .doc(user.uid)
      .set({
    'email': user.email,
    'name': 'John Doe',
  });
}




45. User-Specific Data


A common pattern is to use the authenticated user's UID as the Firestore document ID.


users
  |
  +-- AUTH_USER_UID
       |
       +-- name
       +-- email
       +-- phone
       +-- createdAt

This makes it straightforward to locate the current user's document.




46. Firestore Security Rules


Security Rules are essential for protecting Firestore data. For Flutter mobile and web clients, Firebase recommends using Firebase Authentication together with Cloud Firestore Security Rules to control access and validate data. Cloud Firestore Security Documentation


A basic authenticated-user rule can look like:


rules_version = '2';

service cloud.firestore {
  match /databases/{database}/documents {


    match /users/{userId} {
      allow read, write: if request.auth != null
                         && request.auth.uid == userId;
    }
  }
}


This pattern allows an authenticated user to access the user document whose ID matches their Firebase Authentication UID.




47. Important Security Rule Concept


Firestore Security Rules are not filters. A query must satisfy the constraints required by the rules for all potential documents that could be returned. A query that could return unauthorized documents can fail rather than simply filtering those documents out. Securely Query Cloud Firestore Data




48. Example of Query-Compatible Security


match /stories/{storyId} {
  allow read: if request.auth != null
              && resource.data.author == request.auth.uid;
}

The corresponding client query should constrain the author field:


final user = FirebaseAuth.instance.currentUser;

if (user != null) {
  final snapshot = await FirebaseFirestore.instance
      .collection('stories')
      .where(
        'author',
        isEqualTo: user.uid,
      )
      .get();
}


This query structure reflects the access condition enforced by the rule.




49. Server-Side Access vs Mobile/Web Access


Cloud Firestore Security Rules apply to supported mobile and web client access. Server client libraries use IAM and do not rely on Cloud Firestore Security Rules in the same way. Server-side applications should therefore be secured using the appropriate Google Cloud IAM configuration. Firestore Security Overview




50. Timestamp in Firestore


Firestore supports timestamp values.


await FirebaseFirestore.instance
    .collection('posts')
    .add({
  'title': 'Flutter Course',
  'createdAt': Timestamp.now(),
});

You can read the timestamp:


final data = doc.data();

final Timestamp? timestamp = data?['createdAt'];


if (timestamp != null) {
  final date = timestamp.toDate();
  print(date);
}




51. Server Timestamp


When you want Firestore to assign the server-side timestamp, use FieldValue.serverTimestamp().


await FirebaseFirestore.instance
    .collection('posts')
    .add({
  'title': 'Flutter Course',
  'createdAt': FieldValue.serverTimestamp(),
});



52. Increment Numeric Values


Firestore supports atomic numeric increments.


await FirebaseFirestore.instance
    .collection('products')
    .doc('product001')
    .update({
  'views': FieldValue.increment(1),
});

This can be useful for counters such as views, likes, or quantities when used according to the application's concurrency and data-model requirements.




53. Array Operations


Firestore supports atomic array operations such as adding or removing values.


Add an Item to an Array


await FirebaseFirestore.instance
    .collection('users')
    .doc('user001')
    .update({
  'skills': FieldValue.arrayUnion(['Firebase']),
});

Remove an Item from an Array


await FirebaseFirestore.instance
    .collection('users')
    .doc('user001')
    .update({
  'skills': FieldValue.arrayRemove(['Firebase']),
});



54. Nested Objects


Firestore documents can contain nested map structures.


await FirebaseFirestore.instance
    .collection('users')
    .doc('user001')
    .set({
  'name': 'John',
  'address': {
    'city': 'Mumbai',
    'country': 'India',
    'postalCode': '400001',
  },
});



55. Access Nested Data


final data = doc.data();

final address = data?['address'];


if (address != null) {
  print(address['city']);
  print(address['country']);
}




56. Subcollection Example


final userRef = FirebaseFirestore.instance
    .collection('users')
    .doc('user001');

await userRef
    .collection('orders')
    .doc('order001')
    .set({
  'product': 'Flutter Course',
  'price': 5000,
  'status': 'pending',
});


The resulting structure is:


users
  |
  +-- user001
       |
       +-- orders
            |
            +-- order001
                 |
                 +-- product
                 +-- price
                 +-- status



57. Read a Subcollection


final snapshot = await FirebaseFirestore.instance
    .collection('users')
    .doc('user001')
    .collection('orders')
    .get();

for (final doc in snapshot.docs) {
  print(doc.data());
}




58. Real-Time Chat Example


Firestore real-time listeners can be used for chat applications.


StreamBuilder(
  stream: FirebaseFirestore.instance
      .collection('messages')
      .orderBy('createdAt')
      .snapshots(),
  builder: (context, snapshot) {
    if (!snapshot.hasData) {
      return const CircularProgressIndicator();
    }

    final messages = snapshot.data!.docs;


    return ListView.builder(
      itemCount: messages.length,
      itemBuilder: (context, index) {
        final message = messages[index].data();


        return ListTile(
          title: Text(message['text'] ?? ''),
          subtitle: Text(message['sender'] ?? ''),
        );
      },
    );
  },
)




59. Pagination Concept


When a collection contains many documents, loading everything at once may not be appropriate. Firestore supports query cursors that can be used to retrieve data in pages.


A common pagination flow is:


First Page
   |
   v
Get Documents
   |
   v
Remember Last Document
   |
   v
Request Next Page
   |
   v
Display More Documents

Pagination should be designed around the application's sorting and filtering requirements.




60. Transactions


Transactions are useful when a group of reads and writes needs to operate consistently based on the current database values.


await FirebaseFirestore.instance.runTransaction(
  (transaction) async {
    final ref = FirebaseFirestore.instance
        .collection('products')
        .doc('product001');

    final snapshot = await transaction.get(ref);


    final currentStock = snapshot.data()?['stock'] ?? 0;


    if (currentStock > 0) {
      transaction.update(ref, {
        'stock': currentStock - 1,
      });
    }
  },
);




61. Batch Writes


Batch writes can be used when multiple write operations should be sent together.


final batch = FirebaseFirestore.instance.batch();

final userRef = FirebaseFirestore.instance
    .collection('users')
    .doc('user001');


final orderRef = FirebaseFirestore.instance
    .collection('orders')
    .doc('order001');


batch.set(userRef, {
  'name': 'John',
});


batch.set(orderRef, {
  'product': 'Flutter Course',
});


await batch.commit();




62. Error Handling


Firestore operations should handle errors because network problems, permissions, invalid operations, and other conditions can cause a request to fail.


try {
  await FirebaseFirestore.instance
      .collection('users')
      .doc('user001')
      .set({
    'name': 'John',
  });
} catch (e) {
  print('Firestore error: $e');
}



63. Firestore Exception Handling


You can handle Firestore-specific exceptions using FirebaseException.


try {
  await FirebaseFirestore.instance
      .collection('users')
      .doc('user001')
      .get();
} on FirebaseException catch (e) {
  print('Code: ${e.code}');
  print('Message: ${e.message}');
} catch (e) {
  print('Unexpected error: $e');
}



64. Loading, Error, Empty, and Success States


A Firestore-based screen should generally handle four important states:



  • Loading

  • Error

  • Empty

  • Success


if (snapshot.connectionState == ConnectionState.waiting) {
  return const CircularProgressIndicator();
}

if (snapshot.hasError) {
  return const Text('Unable to load data');
}


if (!snapshot.hasData || snapshot.data!.docs.isEmpty) {
  return const Text('No data available');
}


return const Text('Data loaded successfully');




65. Convert Firestore Documents to Dart Models


For larger applications, it is better to convert Firestore documents into Dart model classes instead of passing raw maps throughout the UI.


User Model


class UserModel {
  final String id;
  final String name;
  final String email;

  UserModel({
    required this.id,
    required this.name,
    required this.email,
  });


  factory UserModel.fromFirestore(
    DocumentSnapshot> doc,
  ) {
    final data = doc.data() ?? {};


    return UserModel(
      id: doc.id,
      name: data['name'] ?? '',
      email: data['email'] ?? '',
    );
  }
}




66. Using the User Model


final snapshot = await FirebaseFirestore.instance
    .collection('users')
    .get();

final users = snapshot.docs
    .map(UserModel.fromFirestore)
    .toList();


for (final user in users) {
  print(user.name);
  print(user.email);
}




67. Firestore Service Class


Firestore operations can be separated into a service class.


class UserService {
  final FirebaseFirestore _db = FirebaseFirestore.instance;

  Future addUser({
    required String id,
    required String name,
    required String email,
  }) async {
    await _db.collection('users').doc(id).set({
      'name': name,
      'email': email,
      'createdAt': FieldValue.serverTimestamp(),
    });
  }


  Future>> getUser(
    String id,
  ) {
    return _db.collection('users').doc(id).get();
  }


  Future updateUser(
    String id,
    Map data,
  ) {
    return _db.collection('users').doc(id).update(data);
  }


  Future deleteUser(String id) {
    return _db.collection('users').doc(id).delete();
  }
}




68. Recommended Project Structure


lib/
├── main.dart
├── firebase_options.dart
├── models/
│   ├── user_model.dart
│   └── product_model.dart
├── services/
│   ├── auth_service.dart
│   └── firestore_service.dart
├── screens/
│   ├── home_screen.dart
│   ├── users_screen.dart
│   └── products_screen.dart
├── widgets/
│   ├── user_card.dart
│   └── product_card.dart
└── repositories/
    └── user_repository.dart



69. Firestore and Flutter UI


A common Flutter architecture separates the UI from database operations.


Flutter UI
    |
    v
Controller / ViewModel
    |
    v
Repository / Service
    |
    v
Cloud Firestore
    |
    v
Firebase Backend

This structure makes the code easier to test, maintain, and expand as the application grows.




70. Example Product Application


Suppose an application stores products in Firestore:


products
  |
  +-- product001
  |     +-- name: "Laptop"
  |     +-- price: 65000
  |     +-- category: "Electronics"
  |
  +-- product002
        +-- name: "Phone"
        +-- price: 35000
        +-- category: "Electronics"

Add Product


await FirebaseFirestore.instance
    .collection('products')
    .add({
  'name': 'Laptop',
  'price': 65000,
  'category': 'Electronics',
});

Read Products


final snapshot = await FirebaseFirestore.instance
    .collection('products')
    .get();

Update Product


await FirebaseFirestore.instance
    .collection('products')
    .doc('product001')
    .update({
  'price': 62000,
});

Delete Product


await FirebaseFirestore.instance
    .collection('products')
    .doc('product001')
    .delete();



71. Offline Support


Cloud Firestore provides offline capabilities on supported platforms. The client can cache data that the application is actively using and can continue to read, write, listen to, and query cached data while offline. When connectivity returns, local changes are synchronized with the backend. Firestore Offline Data Documentation


Offline behavior should still be considered when designing user interfaces because users may temporarily have no network connection.




72. Firestore Console


The Firebase Console provides a visual interface for managing Firestore data.


You can use the console to:



  • Create collections.

  • Create documents.

  • Edit documents.

  • Delete documents.

  • Inspect document fields.

  • Review database data.

  • Manage indexes and database configuration.


Firestore data can be managed from the Firestore Data tab in the Firebase Console. Firestore Console Documentation




73. Firestore Indexes


Indexes help Firestore efficiently execute supported queries. Some compound queries require an index. When a required index is missing, Firestore can return an error containing a link to create the required index.


When designing queries, understand the fields used for filtering and sorting so that required indexes can be configured appropriately.




74. Firestore Security Best Practices



  • Do not leave production Firestore data publicly readable and writable.

  • Use Firebase Authentication for user identity.

  • Use Security Rules to control document access.

  • Use UID-based rules for user-specific documents.

  • Validate incoming data with Security Rules where appropriate.

  • Design queries to satisfy the constraints imposed by Security Rules.

  • Use App Check where appropriate as an additional protection layer.

  • Do not place secret server credentials inside a Flutter application.

  • Review rules before releasing the application.


Firebase recommends Authentication and Security Rules for mobile and web client access to Firestore. Firestore Security Rules Overview




75. Common Firestore Mistakes












Mistake Better Approach
Using incorrect collection/document paths Keep the Firestore data model clearly documented.
Loading an entire large collection unnecessarily Use filtering, limits, pagination, and appropriate queries.
Ignoring loading and error states Handle loading, error, empty, and success states.
Using raw maps everywhere Use Dart model classes for larger applications.
Ignoring Security Rules Design and test rules before production.
Assuming Security Rules filter query results Make queries satisfy the constraints required by the rules.
Calling database operations unnecessarily Use appropriate state management and caching patterns.
Ignoring offline behavior Design the UI to handle temporary network issues.



76. Firestore vs Realtime Database










Feature Cloud Firestore Realtime Database
Data Model Collections and documents JSON tree
Queries Rich querying capabilities Query capabilities differ
Real-Time Updates Supported Supported
Offline Support Supported on supported client platforms Supported
Hierarchical Data Documents and subcollections Nested JSON structure
Security Security Rules Security Rules

The appropriate Firebase database depends on the application's data model, query requirements, real-time needs, and other technical considerations.




77. Mini Project: Flutter User Management App


Create a Flutter application that uses Firebase Authentication and Cloud Firestore to manage users.


Required Features



  1. User registration.

  1. User login.

  1. Firebase Authentication.

  1. Store user profile in Firestore.

  1. Display current user information.

  1. Update profile information.

  1. Display a list of users where permitted by Security Rules.

  1. Delete a user profile document where permitted.

  1. Logout.

  1. Loading and error states.


Suggested Firestore Structure


users
  |
  +-- USER_UID
       |
       +-- name
       +-- email
       +-- phone
       +-- createdAt
       +-- profileImage



78. Mini Project: Product Management App


Create a product management application using Cloud Firestore.


Features



  • Add products.

  • Display products.

  • Search or filter products using supported queries.

  • Sort products.

  • Update products.

  • Delete products.

  • Display loading state.

  • Display empty state.

  • Display error state.

  • Use Security Rules to restrict write access.




79. Interview Questions



  1. What is Cloud Firestore?

  1. What is the difference between a collection and a document?

  1. What is a Firestore document ID?

  1. What are Firestore subcollections?

  1. How do you add Cloud Firestore to a Flutter project?

  1. What is FirebaseFirestore.instance?

  1. What is the difference between add() and set()?

  1. What is the difference between set() and update()?

  1. How do you retrieve a single Firestore document?

  1. How do you retrieve all documents from a collection?

  1. What is the difference between get() and snapshots()?

  1. How do you display real-time Firestore data in Flutter?

  1. How does StreamBuilder work with Firestore?

  1. How do you filter Firestore documents?

  1. What is where()?

  1. What is orderBy()?

  1. What is limit()?

  1. What are Firestore indexes?

  1. What are Firestore Security Rules?

  1. How do Firebase Authentication and Firestore work together?

  1. Why is a user's Firebase UID useful in Firestore?

  1. What is offline support in Firestore?

  1. What are Firestore transactions?

  1. What are batch writes?

  1. How can Firestore data be converted into Dart model classes?




80. Quick Revision






















Concept Important API
Firestore Instance FirebaseFirestore.instance
Collection collection()
Document doc()
Create with Auto ID add()
Create/Replace set()
Update update()
Read Once get()
Real-Time Data snapshots()
Filter where()
Sort orderBy()
Limit limit()
Delete delete()
Server Timestamp FieldValue.serverTimestamp()
Increment FieldValue.increment()
Array Add FieldValue.arrayUnion()
Array Remove FieldValue.arrayRemove()
Transaction runTransaction()
Batch Write batch()



81. Learning Outcomes


After completing this topic, you should be able to:



  • Explain Cloud Firestore and its NoSQL data model.

  • Understand collections, documents, fields, and subcollections.

  • Configure Cloud Firestore in a Flutter application.

  • Add documents with automatic and custom IDs.

  • Read individual and multiple documents.

  • Update and delete Firestore data.

  • Use Firestore queries.

  • Filter and sort Firestore data.

  • Display Firestore data using FutureBuilder.

  • Display real-time Firestore data using StreamBuilder.

  • Use timestamps and atomic field operations.

  • Work with nested data and subcollections.

  • Use Firestore with Firebase Authentication.

  • Understand Firestore Security Rules.

  • Handle loading, error, empty, and success states.

  • Use Dart models and service classes for scalable applications.

  • Understand transactions, batch writes, pagination, and offline support.




82. Official Firebase Resources













83. JustAcademy Flutter Resources


For structured Flutter learning, practical development training, and additional Flutter topics, explore the following resources:








84. Summary


Cloud Firestore is a flexible NoSQL cloud database that stores data using collections and documents. Flutter applications can use the Cloud Firestore Flutter plugin to create, read, update, delete, query, and listen to application data.


Firestore can be combined with Firebase Authentication to create user-specific data structures, while Security Rules help control access to documents. Real-time listeners make Firestore useful for applications such as chat systems and live dashboards, while queries, indexes, transactions, batch writes, and offline support provide additional capabilities for building more advanced applications.

whatsapp