Flutter - executing a query on a query with firebase

440 Views Asked by At

I have done some research on the firebase website, but did not find the right solution. I have understood that with Firebase, we can not have several where in a query because 'and' is not handled by Firebase. After some research, I found that we can do a query on a query. This is the solution for what I am trying to do. Here, I want to get all the tasks without empty field in Start and Due date.

Below you will find the code. I am using a stream. When I will have executed the query on a query, I want to use the result to populate a SfCalendar widget. Thank you

First test

Stream<QuerySnapshot> getAllTasksStreamSnapShots (BuildContext context) async*{

    yield* FirebaseFirestore.instance
        .collection('Users')
        .doc(FirebaseAuth.instance.currentUser!.uid)
        .collection('allTasks')
        .where('task_Start_Date', isNotEqualTo: '')
       // .where('task_Due_Date', isNotEqualTo:  '') 
        .snapshots();

    /*final myQuery1 = FirebaseFirestore.instance
        .collection('Users')
        .doc(FirebaseAuth.instance.currentUser!.uid)
        .collection('allTasks')
        .where('task_Start_Date', isNotEqualTo: '')
    // .where('task_Due_Date', isNotEqualTo:  '')
        .snapshots();*/
  }
}

If I add the second where clause, I am getting this error

Dart Unhandled Exception: 'package:cloud_firestore/src/query.dart': Failed assertion: line 720 pos 16: '!hasNotEqualTo': You cannot use '!=' filters more than once., stack trace: #0 _AssertionError._doThrowNew (dart:core-patch/errors_patch.dart:51:61)

Stream<QuerySnapshot> getAllTasksStreamSnapShots (BuildContext context) async*{

   final myQuery1 = FirebaseFirestore.instance
        .collection('Users')
        .doc(FirebaseAuth.instance.currentUser!.uid)
        .collection('allTasks')
        .where('task_Start_Date', isNotEqualTo: '')
    // .where('task_Due_Date', isNotEqualTo:  '')
        .snapshots();

    var myQuery2 = myQuery1
        .where('task_Due_Date', isNotEqualTo:  '')
        .get();
}

with this one, I am getting several errors.

The argument type 'String' can't be assigned to the parameter type 'bool Function(QuerySnapshot<Map<String, dynamic>>)'.

The named parameter 'isNotEqualTo' isn't defined.

The method 'get' isn't defined for the type 'Stream'.

Future getDatesNotEmpty() async {

    var data = FirebaseFirestore.instance
        .collection('Users')
        .doc(FirebaseAuth.instance.currentUser!.uid)
        .collection('allTasks')
        .where('task_Start_Date', isNotEqualTo: '')
        .get();

    var data2 = data.where('task_Due_Date', isNotEqualTo: '')
  }

With this third option, the error is:

The method 'where' isn't defined for the type 'Future'.

Here is the Fourth test


final myQuery1 = FirebaseFirestore.instance
        .collection('Users')
        .doc(FirebaseAuth.instance.currentUser!.uid)
        .collection('allTasks')
        .where('task_Start_Date', isNotEqualTo: '');

    var myQuery2 = myQuery1.firestore.collection('Users')
        .doc(FirebaseAuth.instance.currentUser!.uid)
        .collection('allTasks')
        .where('task_End_Date', isNotEqualTo: '');

    print('Size record');
    print(myQuery2.snapshots().length);


on the fourth test, when I try to print the number of record, I am getting this 'Instance of 'Future' instead of a number.

1

There are 1 best solutions below

2
Peter Obiechina On

In the first test:

You can not use '!=' filters more than once as the error tells you.

A way around that would be to create another field called has_start_and_end_date. This field should be set to true if start_date and end_date are not empty. Then, you can then call

Stream<QuerySnapshot> getAllTasksStreamSnapShots() {
  return FirebaseFirestore.instance
      .collection('Users')
      .doc(FirebaseAuth.instance.currentUser!.uid)
      .collection('allTasks')
      .where('has_start_and_end_date', isEqualTo: true)
      .snapshots();
}

NB: This query returns every task document where the has_start_and_end_date field exists with a value equal to true.

You can update the has_start_and_end_date field using cloud functions or whereever you set the value of start_date and end_date in your code.

In the second test:

snapshots() would return type a stream (Stream<QuerySnapshot>) and it has no where firestore filter method (it has the list method where).

In the second test:

get() would return type a future (Future<QuerySnapshot>) and it has no where method.

EDIT: You can also get the list of tasks from firebase and filter on the user's device.

Future<List<Map<String, dynamic>>> getAllTasksStreamSnapShots() async {
  final taskDocs = await FirebaseFirestore.instance
      .collection('Users')
      .doc(FirebaseAuth.instance.currentUser!.uid)
      .collection('allTasks')
      .where('task_Start_Date', isNotEqualTo: '')
      .get();
  final tasks = taskDocs.docs.map((e) => e.data()).toList();
  tasks.removeWhere((e) => (e['task_End_Date'] as String).isEmpty);
  return tasks;
}

and you can utilise this like this: final tasks = await getAllTasksStreamSnapShots();

NB: This will incur extra costs (For reading tasks where task_End_Date is empty)