Miguel Chavez
Miguel Chavez

Reputation: 171

Not getting all the documents in a collection Firebase Function

I am trying to get all the documents in a collection and .forEach document do a query of a sub collection and get the latest (by date) document out of it, but for some reason the query size always is 0

Here is the code:

import * as functions from "firebase-functions";
import * as admin from "firebase-admin";

/// Updates the last payment done in the neighbors documents
export const updateLastPaymentHTTP = functions.https.onRequest(
  async (request, response) => {
    try {
      const neighbors = await admin.firestore()
                                   .collection("neighbors").get();
      const promises = [];
      neighbors.forEach(async (neighbor) => {
        const topPaymentRef = admin.firestore()
                                   .collection(`neighbors/${neighbor.ref}/payments`)
                                   .orderBy("date", "desc")
                                   .limit(1)
                                   .get();
        const querySize = await topPaymentRef.then((query) => query.size);
        console.log(`Query Size: ${querySize}`);
        if (querySize === 1) {
          const lastPayment = (await topPaymentRef).docs[0].data();
          promises.push(neighbor.ref.update({ last_payment: lastPayment }));
        } else {
          promises.push(neighbor.ref.update({ last_payment: "" }));
        }
      });
      await Promise.all(promises);
      response.send("Update Last Payments Completed");
    } catch (error) {
      console.log(`Error Updating Last Payment ${error}`);
    }
  }
);

I do the query check because in some neighbor documents there is not a sub collection called payments but in most of them there is:

With Payments

and

Without Payments

But my querySize === 1 is always false and i update { last_payment: '' }. I have also tried every option explained here, Is there something wrong with my collection query?

Upvotes: 0

Views: 115

Answers (2)

Miguel Chavez
Miguel Chavez

Reputation: 171

Following up Renaud code and Doug solution I found that the problem was related to the neighbor.ref I changed to neighbor.ref.id then everything worked, Here is my changes in Renaud's code:

First I added a constant so save each of the neighbors ids and add them to a list:

  neighbors.forEach((neighbor) => {
    const neighborId = neighbor.ref.id;  /// Here
    promises.push(
      db
        .collection(`neighbors/${neighborId}/payments`)
        .orderBy("date", "desc")
        .limit(1)
        .get()
    );

    neighborsRefsId.push(neighborId);  /// And Here
  });

Then after getting the promises for all neighbors I created a variable named refDoc to save all the references for each query with the idx and updated the documents accordingly.

   const paymentsQuerySnapshotsArray = await Promise.all(promises);

      promises = [];
      paymentsQuerySnapshotsArray.forEach((paymentsQuerySnapshot, idx) => {
        const refDoc = db.doc(`/neighbors/${neighborsRefsId[idx]}`);
        if (paymentsQuerySnapshot.size === 1) {
          const lastPayment = paymentsQuerySnapshot.docs[0].data();
          promises.push(refDoc.update({ last_payment: lastPayment }));
        } else {
          promises.push(refDoc.update({ last_payment: "" }));
        }
      });

Hope this helps others.

Upvotes: 0

Renaud Tarnec
Renaud Tarnec

Reputation: 83068

There are several places in your code that need to be adapted:

The following should work (untested):

export const updateLastPaymentHTTP = functions.https.onRequest(
    async (request, response) => {
        try {

            const db = admin.firestore();

            const neighbors = await db.collection("neighbors").get();

            const neighborsRefs = [];
            let promises = [];

            neighbors.forEach((neighbor) => {

                promises.push(db.collection(`neighbors/${neighbor.ref}/payments`)
                    .orderBy("date", "desc")
                    .limit(1)
                    .get());

                neighborsRefs.push(neighbor.ref);

            });

            const paymentsQuerySnapshotsArray = await Promise.all(promises);

            promises = [];
            paymentsQuerySnapshotsArray.forEach((paymentsQuerySnapshot, idx) => {

                if (paymentsQuerySnapshot.size === 1) {
                    const lastPayment = paymentsQuerySnapshot.docs[0].data();
                    promises.push(neighborsRefs[idx].update({ last_payment: lastPayment }));
                } else {
                    promises.push(neighborsRefs[idx].update({ last_payment: "" }));
                }

            })

            await Promise.all(promises);
            response.status(200).send("Update Last Payments Completed");
        } catch (error) {
            console.log(`Error Updating Last Payment ${error}`);
            response.status(500).send(error.message);
        }
    }
);

Upvotes: 1

Related Questions