1

I have collection of consultations with value 'date' with format of TimeStamp (October 31, 2020 at 1:00:00 AM UTC+1). Another value i have is "status" (true/false)

Every TimeStamp has same time, its allways 1:00:00 AM UTC+1.

I would like to set "status" to false, if the date is tomorrow or it has been already gone.

Here is my cloud function that I tried to make by myself:

exports.scheduledFunction = functions.pubsub
  .schedule("* 1 * * *")
  .timeZone("Europe/Prague")
  .onRun(async () => {
    const tommorow = new Date().getTime() + 24*60*60;

    await firebase.firestore
      .collection("consultations")
      .where("date" '==' tommorow)
      .set((status: false), { merge: true });
  });

enter image description here

GalAbra
  • 5,048
  • 4
  • 23
  • 42
Dima Malko
  • 227
  • 2
  • 19
  • Most often you'll need to do a range query (`date > a && date < b`) to select all documents in that range. Can you edit your question to show a screenshot of a document with the date? – Frank van Puffelen Nov 05 '20 at 14:14
  • @FrankvanPuffelen I have added the screenshot, if this is what you need :) – Dima Malko Nov 05 '20 at 14:21
  • `where()` returns a Query object which does not have a `set()` method. You have to iterate the query results and call `set()` on each document reference individually. – Doug Stevenson Nov 05 '20 at 15:58

3 Answers3

2

You're storing Firestore timestamp's in the database.

There are two problems with the code you shared:

  1. Your tommorow variable is a number (the number of milliseconds since the epoch). Since you store date/time in Firestore, you're trying to compare a number with a date/time, which will never match.

  2. Since you're storing a date/time, getting the documents for a day is a range operation. You want all documents between date/time A and date/time B.

If you want all documents with a date/time between now and 24 hours from now, that'd be:

const nowTimestamp = Date.now();
const now = new Date(nowTimestamp);
const tommorow = new Date(nowTimestamp + 24*60*60*1000);

firebase.firestore
  .collection("consultations")
  .where("date", '>=', now)
  .where("date", '<', tomorrow)

Another problem in your code that you're trying to call set on a query, which is not possible. You'll need to:

  1. Execute the query to get the documents that match it.
  2. Loop over the documents in your code.
  3. Update each document in turn.

For more on this, I recommend checking out: How to use where and update

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
1
    .onRun(async () => {
    const tomorrow = new Date();
    const tmp = tomorrow.getDate() + 1;
    tomorrow.setDate(tmp);

    const data = await db
      .collection("consultations")
      .where("status", "==", true)
      .where("date", "<", tomorrow)
      .get();

    return Promise.all(
      data.docs.map((item) => item.ref.set({ status: false }, { merge: true }))
    );
  });

Thank you everyone for your advices, this is what finall working code is looking now :)

Dima Malko
  • 227
  • 2
  • 19
0

You can use JS's native Date objects to query TimeStamps.

async function updateListingsByDate(operator, date) {
  await firebase.firestore
    .collection("consultations")
    .where('date', operator, date)
    .set((status: false), { merge: true });
}

Hence, you can update the listings that occur tomorrow using:

async function updateTomorrow() {
  const tomorrow = new Date();
  const tmp = tomorrow.getDate() + 1;
  tomorrow.setDate(tmp);

  return updateListingsByDate('==', tomorrow);
}

And similarly update the listings that occurred before today:

async function updatePastDates() {
  return updateListingsByDate('<', new Date());
}
GalAbra
  • 5,048
  • 4
  • 23
  • 42