skip to Main Content

i want to create a page in my app where i view history of previously entered data from firestore according to date.I have a page where i try to fetch data specific to date entered, but it seems to keep returning duplicate data as shown in the image belowenter image description here

I only want to be able to show a date particular date once in this page but i cant seem to do that. here is the code

StreamBuilder(
                    stream: FirebaseFirestore.instance
                        .collection('users')
                        .doc(user?.uid)
                        .snapshots(),
                    builder: (context, AsyncSnapshot snapshot) {
                      print(snapshot.data.docs);
                      if (snapshot.hasError) {
                        Get.snackbar(
                          'About Task',
                          'User message',
                          backgroundColor: Colors.white,
                          snackPosition: SnackPosition.BOTTOM,
                          titleText: const Text(
                            'Failed Adding Task',
                            style: TextStyle(color: Colors.red),
                          ),
                          messageText: const Text(
                            'Something went wrong... Try again',
                            style: TextStyle(color: Colors.red),
                          ),
                        );
                      }
                      if (snapshot.data == null) {
                        const Center(
                          child: Text('Add a task/Transaction'),
                        );
                      }
                      if (snapshot.connectionState == ConnectionState.waiting) {
                        return const Center(
                          child: CircularProgressIndicator(),
                        );
                      }
                      if (snapshot.hasData) {
                        final List storeDocs = [];
                        snapshot.data!.docs.map((DocumentSnapshot document) {
                          Map a = document.data() as Map<String, dynamic>;
                          storeDocs.add(a);
                          a['id'] = document.id;
                        }).toList();
                        Calculations.getTotalBalance(storeDocs.asMap());
                        return ListView.builder(
                            shrinkWrap: true,
                            itemCount: snapshot.data.docs.length,
                            itemBuilder: (context, index) {
                              TaskModel task =
                                  TaskModel.fromJson(snapshot.data.docs[index]);
                              print(Expenses.multipleDates);
                              return Container(
                                decoration: BoxDecoration(),
                                child: Column(
                                  children: [
                                    SizedBox(
                                      height: 25,
                                    ),
                                    Row(
                                      mainAxisAlignment:
                                          MainAxisAlignment.spaceBetween,
                                      crossAxisAlignment:
                                          CrossAxisAlignment.start,
                                      children: [
                                        Row(
                                          children: [
                                            Container(
                                              width: 53,
                                              height: 80,
                                              child: Text(
                                                task.date,
                                                style: TextStyle(fontSize: 10),
                                              ),
                                            ),
                                          ],
                                        ),
                                        Text(
                                          task.amount,
                                          style: const TextStyle(
                                              fontSize: 15,
                                              fontWeight: FontWeight.w600,
                                              color: Colors.green),
                                        ),
                                        Column(
                                          children: [
                                            Row(
                                              children: [
                                                Text(
                                                  task.amount,
                                                  style: const TextStyle(
                                                      fontSize: 15,
                                                      fontWeight:
                                                          FontWeight.w600,
                                                      color: Colors.red),
                                                ),
                                              ],
                                            ),
                                            SizedBox(
                                              height: 22,
                                            ),
                                            Row(
                                              children: [
                                                GestureDetector(
                                                  onTap: () {
                                                    _showBottomSheet(
                                                        context, task);
                                                  },
                                                  child: GestureDetector(
                                                    onTap: () {
                                                      Navigator.pushNamed(
                                                          context,
                                                          SpreadSheetPage.id,
                                                          arguments: Tasks(
                                                            firestoreDocID:
                                                                task.date,
                                                          ));
                                                    },
                                                    child: Text(
                                                      'View',
                                                      style: TextStyle(
                                                          color: Colors.blue),
                                                    ),
                                                  ),
                                                ),
                                              ],
                                            )
                                          ],
                                        ),
                                      ],
                                    ),
                                    const Padding(
                                      padding:
                                          EdgeInsets.only(left: 65, top: 8),
                                      child: Divider(
                                        thickness: 0.8,
                                      ),
                                    )
                                  ],
                                ),
                              );
                            });
                      } else {
                        return Container();
                      }
                    }),

here is what my database looks like
enter image description here

2

Answers


  1. You just need to add a filter on the collection:

      .collection('tasks')
      .where('date', isEqualTo: selectedDate)
      .snapshots()
    
    Login or Signup to reply.
  2. Based on your feedback, here’s what I’d do.

    Note how you can’t filter the query for duplicate values directly in your query.

    There is no way to tell Firestore "get all of the results from this collection, but filter out elements that have a field repeated (or duplicated) in the collection itself". This makes sense since the Firestore SDK performs simple and fast queries through the where clause. Read the docs for more info.

    This means that the filtering is at your expenses, i.e. you have to implement it yourself and you will be charged for all of the reads you do. Note: any workaround to reduce the number of reads (e.g. use the not-in clause) is hacky, hard to read and maintain and it just doesn’t work for a large dataset (not-in would limit your duplicates to 10, in your case), so embrace it.

    Considering these premises one could implement the following brute-force solution that reads all the documents from your firestore collection and filters out the duplicates by exploiting a simple Set:

    Future<List> getAndFilter() async {
      final f = FirebaseFirestore.instance;
    
      final data = await f.collection('myCollection').get();
      final unfilteredData = [for (final d in data.docs) d.data()];
    
      final seenValues = Set();
      final desiredData = unfilteredData.where((currentDoc) {
        if (seenValues.contains(currentDoc)) return false;
    
        seenValues.add(currentDoc);
        return true;
      });
      
      return desiredData.toList();
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search