2

I have a Firestore database which contains a list of documents in a collection. Each document has a scheduled date which is a "timestamp" data type. I'm able to get data by the scheduled date, but not able to get all documents not equal to a particular scheduled date. So what I have done is filtered all data with not equal to the scheduled date in frontend but there is a tradeoff I have to store all collection documents in front-end

Below query for getting data by a scheduled date.

where: [
        [
          'ScheduleDateTime',
          '>=',
          new Date('2020-02-12 00:00:00'),
        ],
        [
          'ScheduleDateTime',
          '<=',
          new Date('2020-02-12 23:59:59'),
        ],
      ],

Logic I built-in front-end side for not equal date.

const Quotations =
    allDocuments.filter(
      ele =>
        scheduledDateList.indexOf(
          ele.id
        ) == -1
    );

We already know that we cant use != or OR condition in firestore. It's very difficult to work on firestore. Any suggestions or solutions will be helpful.

Nishant Singh
  • 477
  • 4
  • 8

1 Answers1

1

As you have mentioned in your question, and as explained in the doc:

Cloud Firestore does not support the following types of queries:

  • Queries with a != clause are not supported. In this case, split the query into a greater-than query and a less-than query. ...
  • Logical OR queries. In this case, you should create a separate query for each OR condition and merge the query results in your app.

The following function will merge two queries based on the ScheduleDateTime timestamp fields:

  async function getDatesNotEqual() {

    const isLess = datesRef
      .where(
        'ScheduleDateTime',
        '<=',
        firebase.firestore.Timestamp.fromDate(
          new Date('2020-02-12 00:00:00')
        )
      )
      .get();

    const isMore = datesRef
      .where(
        'ScheduleDateTime',
        '>',
        firebase.firestore.Timestamp.fromDate(
          new Date('2020-02-12 23:59:59')
        )
      )
      .get();

    const [isLessQuerySnapshot, isMoreQuerySnapshot] = await Promise.all([
      isLess,
      isMore
    ]);

    const isLessThanDocsArray = isLessQuerySnapshot.docs;
    const isMoreThanDocsArray = isMoreQuerySnapshot.docs;

    return _.concat(isLessThanDocsArray, isMoreThanDocsArray);
  }


  //Here we call the async function
  getDatesNotEqual().then(result => {
    result.forEach(docSnapshot => {
      console.log(docSnapshot.data());
    });
  });

Note that we use the Lodash library to merge the two Arrays (_.concat()), but you could use other techniques to do so.


Also note that we use the fromDate() method of the Firestore Timestamp to build the queries.

Renaud Tarnec
  • 79,263
  • 10
  • 95
  • 121
  • Hi Renaud, already familiar with this solution. I'm looking for something that can solve this issue in a single query. As you suggested that we can use the `fromDate()` but its better to go with the javascript `Date()` as there is no difference between them. In both the cases I have to pass date and time as String to `new Date()` – Nishant Singh Feb 12 '20 at 09:14
  • @NishantSingh Hi, if you want to base your query on the unique `ScheduleDateTime` field there is no way to solve it with only one query. – Renaud Tarnec Feb 12 '20 at 09:29