Firestore: Unable to fetch document from query - doc.data is not a function - javascript

here usersList contains the list of username of people and androidNotificationToken is the field in the document of the user which contains the token for sending the notification.
const registrationTokens=[];
const indexOfSender=usersList.indexOf(senderUsername); // to remove the name of person sending message
let removedUsername=usersList.splice(indexOfSender,1);
usersList.forEach(async(element)=>{
const userRef = admin.firestore().collection('users').where("username","==",element);
const doc = await userRef.get();
registrationTokens.push(doc.data().androidNotificationToken);
});
The error on running the cloud computing am receiving is :-
TypeError: doc.data is not a function
at usersList.forEach (/workspace/index.js:191:37)
at process._tickCallback (internal/process/next_tick.js:68:7)

userRef.get() is going to return a QuerySnapshot (not a DocumentSnapshot) object that can contain 0 or more documents matched from the query. Use the API provided by QuerySnapshot to find the resulting documents, even if you are expecting only one document.
If you are expecting just one document from the query, you should at least verify that you got one before indexing into the result set.
const query = admin.firestore().collection('users').where("username","==",element);
const qsnapshot = await query.get();
if (qsnapshot.docs.length > 0) {
const doc = qsnapshot.docs[0];
const data = doc.data();
}
else {
// decide what you want to do if the query returns nothing
}

Related

How to get the complete document path in firebase firestore?

I managed to get all the documents and document IDs inside all 'sheets' collection in firestore.
Refer to below code -
const baseRef = admin.firestore().collectionGroup("sheets").where("date", "==", date);
const querySnap = await baseRef.get();
const docSnap = querySnap.docs;
docSnap.forEach((doc) => {
console.log("DOC ID ---->>>", doc.id);
// Here I want to get all the required documents from 'members' subcollection present inside this document
});
Now each of these documents contain a subcollection called 'members'. I want only documents from 'members' collection where "memberId" is equal to 'memberId'. How can I get those documents?
I tried the following code but it didn't worked -
const baseRef = admin.firestore().collectionGroup("sheets").where("date", "==", date).collectionGroup("members").where("memberId", "==", memberId);
const querySnap = await baseRef.get();
const docSnap = querySnap.docs;
docSnap.forEach((doc) => {
console.log("DOC ID ---->>>", doc.id);
});
It returned following error -
admin.firestore(..).collectionGroup(..).....is not a function
You cannot define a Query by calling twice the collectionGroup() method as you do with:
const baseRef = admin.firestore().collectionGroup("sheets").where("date", "==", date).collectionGroup("members").where("memberId", "==", memberId);
One solution would be to replicate the date field in the member documents (i.e. copying the field value from the parent sheet docs to their member children docs) and define the Query as follows:
const baseRef = admin.firestore().collectionGroup("members").where("memberId", "==", memberId).where("date", "==", date);
Note that you'll need to build a composite index and that you should not have other subcollections named members in your database.

Firebase function error: Cannot convert undefined or null to object at Function.keys (<anonymous>)

Description of the problem:
My App aim is to store family spending in Firebase Realtime Database. I want that, when a new spending is stored, a notification is sent to all other devices.
I try to send a notification to a single device and it works fine, but when I try to get all the tokens in an array, I have an error:
TypeError: Cannot convert undefined or null to object at Function.keys ().
code of index.js :
const functions = require("firebase-functions");
const admin = require("firebase-admin");
admin.initializeApp();
exports.androidPushNotification = functions.database
.ref("{nodo}/spese/{spesaPush}")
.onCreate(async (snapshot, context) => {
const original = snapshot.val();
const getDeviceTokensPromise = admin.database()
.ref(`/utenti/{tutti}/token`).once('value');
let tokensSnapshot;
let tokens;
tokensSnapshot = await getDeviceTokensPromise;
// This is the line generating the errors.
// If I get only a specific token and
// use tokens = tokensSnapshot.val(); anything works fine
tokens = Object.keys(tokensSnapshot.val());
const result = original.chi + " ha speso " +
original.costo + " € per acquistare " +
original.desc;
console.log(result);
const payload = {
notification: {
title: 'New spending inserted!',
body: result,
}
};
const response = await admin.messaging().sendToDevice(tokens, payload);
return result;
});
It seems that values are not reached yet, but I thought that the keyword await lets system to wait until all data are available. From the log I noticed that the value I need is null and I don't understand why.
If I use this line of code:
const getDeviceTokensPromise = admin.database()
.ref(`/utenti/SpecificUser/token`).once('value');
....
//then
tokens = tokensSnapshot.val();
The notification is sent to the device that has the token under the name of "SpecificUser"
EDIT:
I provide a pic of my db. I notice that none of the field is null, so I don't know why I see this error
Thank you to anyone that helps me
i had same error and it is solve by database...
when i saw my database values unfortunately i stored undefined value so my whole result got error like you...
see your whole values and fields that store values properly.

How to query for objects with a certain property in a Firestore collection, Firebase

I am trying to query for objects in firestore collection with a certain property, my Firestore DB looks as shown in the below picture.
The below code does not work as I am interested in querying for objects based on the the property inside an object. In this case I want all the cases (objects) with "status"=="treated" Is there a way to do it ?
const db = firebase.firestore();
const casesRef = db.collection("mgm/hospital/cases");
// Create a query against the collection.
var query = casesRef.where("status", "==", "active").limit(25);
const queryRef = query.get();
queryRef.then(function(documentSnapshots) {
const cases = documentSnapshots.docs.map((doc) => doc.data());
console.log(cases);
});
Since the field patientDetails is a map, the following should do the trick:
var query = casesRef.where("patientDetails.status", "==", "active").limit(25);

What does .where.get() return?

i am new this website and to mobile programming.
My questions is:
In firebase i have a collection path with some documents.
.collection(maybe).doc(random)
Each doc has subcollection as well.
Also each doc has data such as:
roomName: randomName
roomPassword: randomPass.
So, now i would like to use the query with .where operator and .get like this:
const docRef=db.collection(‘maybe’)
docRef.where(‘roomName’ ‘==‘ ‘randomName’).get()
My question is what do i get back? As i understand i get the querySnapshot, but i do not fully get how to get the second field in data specifically i.e. how to get roomPass?
const docRef = db.collection(‘maybe’);
const futureSnapshot = docRef.where(‘roomName’,‘==‘,‘randomName’).get();
gives you a promise of snapshot.
You have to "await".
const docRef = db.collection(‘maybe’);
const snapshot = await docRef.where(‘roomName’,‘==‘,‘randomName’).get();
after that you can get your data :
const room = snapshot.data(); // undefined if your query has no results
This link could help you
Happy coding !
EDIT
If your document looks like this :
{
randomName: "a name",
randomPassword: "a password"
}
Then you get your data like that :
const room = snapshot.data(); // undefined if your query has no results
const { randomPassword } = room;

Firebase Database: why do the key/ref in my queried datasnapshot refer to its parent?

I would like to delete an entry from the realtime database that i looked up through a query but i am getting unexpected results for both the ref and key properties.
ref('photos/users/USERID')
.orderByChild('photoname')
.equalTo('photoname i want to look up')
.limitToFirst(1)
.query('once')
.then(snapshot => {
// correct data at 'photos/users/USERID/PHOTOID'
const entry = snapshot.val();
// seems to be the ref to photos/users/USERID'
const ref = snapshot.ref;
// seems to be USERID
const key = snapshot.key
})
Why aren't these the ref/key to the entry i just found? And what is the best approach to remove this entry?
When you execute a query against the Firebase Database, there will potentially be multiple results. So the snapshot contains a list of those results. Even if there is only a single result, the snapshot will contain a list of one result.
Your code needs to take this list into account, and iterate over snapshot.forEach() to get the actual matching item:
ref('photos/users/USERID')
.orderByChild('photoname')
.equalTo('photoname i want to look up')
.limitToFirst(1)
.query('once')
.then(snapshot => {
snapshot.forEach(child => {
const entry = child.val();
const ref = child.ref;
const key = child.key
});
})
Your ref and key are based on ref('photos/users/USERID'), not the filtered subset you have created. Is there any reason you wouldn't call ref('photos/users/USERID/PHOTOID')?

Categories

Resources