Firestore, retrieve specific fields as JSON? - javascript

I'm trying to retrieve specific fields from a given firestore collection (inside of an HTTPSCallable) but I'm getting "nulls" for fields that I know exist and have data. Any ideas what I'm doing wrong?
var docs;
await db
.collection(mycollection)
.where("flag", "==", "true")
.get()
.then((querySnapshot) => {
docs = querySnapshot.docs.map((doc) => {
doc.data();
});
});
return JSON.stringify({ mydocs: docs });

You should avoid using promise chaining and async-await at the same time. The return statement will execute without checking if the promise returned by Firestore is resolved. Try this:
const querySnapshot = await db
.collection(mycollection)
.where("flag", "==", "true")
.get()
const docs = querySnapshot.docs.map((doc) => doc.data());
return JSON.stringify({ mydocs: docs });
If you are using promise chaining then anything that should happen after the promise is resolved should ideally be inside of the then() block:
const myQuery = db.collection(mycollection).where("flag", "==", "true")
return myQuery.get().then((querySnapshot) => {
const docs = querySnapshot.docs.map((doc) => doc.data());
return JSON.stringify({ mydocs: docs });
})

Related

Getting ID of a firestore document using a conditional query in Node,js using then()

I have been try to fetch a firestore document ID using a condition. Something like, if a document has its secret_code field "ABCD12", fetch that document's id. I have been trying to do this with Node.js but it does not seem to be working. The code returns {Promise}
I think I have not understood then() well enough.
`
async function getIdFromSecretCode(secret_code) {
doc_id=0
await userCollection
.where("secret_code", "==", secret_code)
.get()
.then(function (querySnapshot) {
querySnapshot.forEach(function (doc) {
// doc.data() is never undefined for query doc snapshots
doc_id = doc.id;
// console.log(doc_id);
//console.log(doc.id, " => ", doc.data());
});
});
return doc_id;
}
var t= getIdFromSecretCode("ABCD")
console.log(t)
`
The o/p is:
`
PS E:\socketio-unity-main> node mserver.js
Promise { <pending> }
`
I want it to return the document id like "1xccecefgrf"
getIdFromSecretCode is an async function so it will always return a promise. You cannot expect a future result to be available now, so you'll need to embrace promises, also in the main call to getIdFromSecretCode.
Moreover, that promise is currently not resolving to anything useful, so you have to adapt that code a bit:
async function getIdFromSecretCode(secret_code) {
const snapshot = await userCollection
.where("secret_code", "==", secret_code)
.get();
return snapshot.docs[0]?.doc_id;
}
getIdFromSecretCode("ABCD").then(t => {
console.log(t);
});

Not able to access documents in a collection Firestore

I have an array of objects which comes from firestore all_categories.
let docID = getStoreID();
let all_categories = [];
db
.collection("STORES")
.doc(docID)
.collection("CATEGORIES")
.orderBy("CAT_ADDED_ON","desc")
.limit(5).get().then((querySnapshot) => {
querySnapshot.forEach((doc) => {
all_categories.push(doc.data())
})
})
When I console.log(all_categories) It shows it has 2 objects but when I try to iterate through them it shows undefiened.
Like this:
all_categories.forEach(category => {
console.log(category)
})
The console does not print anything.
What can be the problem?
Retrieving data from a database is a asynchronous process you can attach another then to it like this when the previous then is completed it will run the after one.
db.collection("STORES")
.doc(docID)
.collection("CATEGORIES")
.orderBy("CAT_ADDED_ON","desc")
.limit(5)
.get()
.then((querySnapshot) => { querySnapshot.forEach((doc) => { all_categories.push(doc.data())})
.then(()=>{ all_categories.forEach(category => { console.log(category) })
})
get() is asynchronous (returns a Promise) meaning that it will move on to another task before it finishes. The then() method returns a Promise. It takes up to two arguments: callback functions for the success and failure cases of the Promise. Therefore you have to do the following to be able to access the category elements:
let docID = getStoreID();
let all_categories = [];
db
.collection("STORES")
.doc(docID)
.collection("CATEGORIES")
.orderBy("CAT_ADDED_ON","desc")
.limit(5).get().then((querySnapshot) => {
querySnapshot.forEach((doc) => {
all_categories.push(doc.data());
all_categories.forEach(category => {
console.log(category)
})
})
})
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then

Returning a promise but still getting error in Firebase functions logs

I have a function in my firebase functions that looks something like this:
exports.userDeleted = functions.auth.user().onDelete((user) => {
admin
.firestore()
.collection('users')
.where('userID', '==', user.uid)
.get()
.then((querySnapshot) => {
const promises = [];
querySnapshot.forEach((doc) => {
const p = doc.ref.delete();
promises.push(p);
});
return Promise.all(promises);
})
.catch((err) => {
throw new console.log(err);
});
});
This function locates where userID is equal to the logged-in user UID and then deletes that document. When the function is executed, it works very well and very fast, however I still get this error in the logs:
As stated in the documentation, background functions must return a promise to indicate to Cloud Functions that all the async work in a function is complete, and it's safe to clean up and terminate. Right now, your function is returning nothing. The return Promise.all(promises) isn't actually doing what you think it is. What you will need to do instead is return the entire promise chain:
exports.userDeleted = functions.auth.user().onDelete((user) => {
return admin
.firestore()
.collection('users')
.where('userID', '==', user.uid)
.get()
.then((querySnapshot) => {
const promises = [];
querySnapshot.forEach((doc) => {
const p = doc.ref.delete();
promises.push(p);
});
return Promise.all(promises);
})
.catch((err) => {
throw new console.log(err);
});
});

How do I count for async task failures when working with redux?

I'm working with firebase and redux for my react app. Due to a mistake I've made I've reached my daily quote on Firebase but that exposed a weakness in my code because now the whole app doesn't load, with the error being that I've reached my daily quota.
I've tried to fix it by having a catch block for the request that just logs the error but that doesn't really solve the issue.
I'm not quite sure how to approach this as I'm new to React and Redux. If the request fails, then my data now equals... What?
This is my code for one of my actions (one of a few similar requests):
export const fetchWords = projectID => async dispatch => {
const db = firebase.firestore();
const data = await db
.collection("names")
.where("project_ID", "==", projectID)
.orderBy("total_score", "desc")
.get()
.catch((err) =>{
console.log(err)
});
const docsData = [];
data.docs.map(doc => {
docsData.push(doc.data());
});
dispatch({
type: FETCH_WORDS,
payload: docsData
});
};
It currently fails saying Unhandled Rejection (TypeError): Cannot read property 'docs' of undefined.
I think the reason you're getting an error is because the data object has not been defined when the exception is caught.
You could either check that data is not null or undefinfed before you try and access the data.docs property or an alternative would be to use the .then() callback instead.
export const fetchWords = projectID => async dispatch => {
const db = firebase.firestore();
const docsData = [];
db.collection("names")
.where("project_ID", "==", projectID)
.orderBy("total_score", "desc")
.get()
.then(data => data.docs.map(doc => docsData.push(doc.data())))
.catch(err => console.log(err));
dispatch({
type: FETCH_WORDS,
payload: docsData
});
};
const data = await db
.collection("names")
.where("project_ID", "==", projectID)
.orderBy("total_score", "desc")
.get()
.catch((err) =>{
console.log(err)
});
here if promise is rejected data will always be undefined. so it's useful to have check for data for valid value before using it.
if(data !== undefined){
data.docs.map(doc => {
docsData.push(doc.data());
});
}

Perform Firestore query in a JavaScript function

I want to perform a Firestore query in a JavaScript function, but I'm having some difficulties with promises.
Let's say I want to get the document ID from a user. So I have created this JavaScript function:
function getUid(email) {
db.collection("users").where("email", "==", email)
.get()
.then(function(querySnapshot) {
querySnapshot.forEach(function(doc) {
return doc.id;
});
})
.catch(function(error) {
return error;
});
}
Now when I call the function res.send(getUid("user#example.com")), it returns undefined.
Which is the correct syntax to wait until the Firestore query finsished?
get() is an async function, so you need to wrap it into an async function. Also, you are not returning anything from the getUid function - you are just returning inside a forEach parameter. If you want to get all id from the snapshot, you can use the map function.
async function getUids(email) {
const db = admin.firestore();
const querySnapshot = await db.collection("users").where("email", "==", email).get();
const uids = querySnapshot.docs.map((doc) => { return doc.id });
return uids;
}
exports.yourFunction = functions.http.onRequest(async (req, res) => {
const email = // ...
res.send(await getUids(email));
});

Categories

Resources