Reputation: 171
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:
and
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
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
Reputation: 83068
There are several places in your code that need to be adapted:
async/await
with then()
async/await
in a forEach
loop (not really recommended, see https://codeburst.io/javascript-async-await-with-foreach-b6ba62bbf404)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