Getting the Data in snapshot.val() but not able to treat it - javascript

I was making an app and had to fetch data from Realtime Database. I am getting the data in snapshot.val() like this
►{xz0ezxzrpkb:{…}}
▼xz0ezxzrpkb:{blood_group:"B+",cause:"Random Cause",created_on:"08-02-2022",email:"example#gmail.com",location:"Random Location",message:"Random Message",name:"Any_Name",phone_number:"+91 *********"}
And Now I want to access this data. When I am trying snapshot.val()[0].email and
snapshot.val().[0].email I am Getting
undefined (2)
So, I am working in React Native and this is the code
db.ref('/requests/').on('value', (snapshot) => {
console.log(snapshot.val())
console.log(snapshot.val()[0].email)
console.log(snapshot.val().[0].email)
});
The nodes of database are as follows:
Please help me out.

While the approach in Dharmaraj's answer works, I recommend using Firebase's built-in forEach operation, since that ensures that you process the results in the same order the database returns them:
db.ref('/requests/').on('value', (snapshot) => {
snapshot.forEach((childSnapshot) => {
console.log(childSnapshot.key) // "xz0ezxzrpkb"
console.log(childSnapshot.val()) // {blood_group:"B+",cause:"Random Cause", ...
console.log(childSnapshot.val().email) // "example#gmail.com"
console.log(childSnapshot.child('email').val()) // "example#gmail.com"
})
})

The snapshot value is not an object. Try refactoring the code using Object.keys() as shown below:
db.ref('/requests/').on('value', (snapshot) => {
Object.keys(snapshot.val()).forEach((key) => {
const request = snapshot.val()[key];
console.log(key, request.email)
})
});

Related

Firebase Query and how to read the output

Above is my Js code
I have a database that has information regarding the location of an apartment, I am trying to search for a specific property to see if it exists in the database. The user will be able to key into the search box to perform the search.
"propertiesRef" is used to store the user input.
I tried storing the data into "q" that I received from querying the database. But I have no idea how to read the result.
This is the console log for "q", but I don't quite understand the information that is shown, I want to know which output in the console should I be looking at and how do I access them?
The query() function just creates an instance Query. You need to use getDocs() function to actually fetch data from Firestore.
const search = (property) => {
const propertiesRef = collection(db, "flats-table");
const q = query(propertiesRef, where("name", "==", property))
return getDocs(q).then((qSnap) => {
const data = qSnap.docs.map(d => ({ id: d.id, ...d.data() }))
console.log(data);
return data;
})
// or use async-await
// const qSnap = await getDocs(q);
}
Checkout the documentation for more examples.

need help accessing Firestore sub-collection?

I'm a novice when it comes to coding (started teaching myself ~year ago), any help will be much appreciated, thank you in advance.
I saw that there is 3-4 other post on stack overflow on how to access Firestore's sub-collections.
I tried them all and had no luck, hence why I'm posting this as a new question.
right now I have my data set is up as: collection/document.array. And that was fine till now because I just needed to read that data from the array to draw it out in my little React project with .reduce and .map and push new data to that array on input.
this is the code I have right now for getting data from Firestore:
--- in firebase.js ----------------------------------------------------------------------
export const fire = firebase.initializeApp(config);
export const db = fire.firestore()
_________________________________________________________________________________________
--- in events-context.js ----------------------------------------------------------------
const fetchEvents = async () => {
try {
const data = await db.collection('events').get();
setEvents(data.docs.map(doc => ({ ...doc.data(), id: doc.id })));
} catch ({ message }) {
alert(`Error # fetchEvents, Error:${message}`);
}
};
But now I want to add edit and a remove feature, but in order to do that, I need to carry out my array of data into a sub-collection so each individual element from that array had its own id so that I could later target it. so it needs to be set up something like this: collection/document/sub-collection
To access a document inside a collection, you must know the document ID from another source. This can be done by managing the names inside an array of strings or maps that you can then process within your app per your design.
For example: once created, you will have a snapshot of the reference of which you can store the document id inside the parent document:
db.collection("events").doc(id).update({
payers: firebase.firestore.FieldValue.arrayUnion(paySnapshot.ref.id)
})`
Once you have this information, you can append it to the relevant document path using one of the following techniques.
db.collection("events").doc(id).collection("payers").doc(pay_id).get()
db.doc(\events/${id}/payers/${pay_id}`).get()`
I strongly advise against using .get() on a collection without limit() and where() conditions to reduce the reads that can occur.
Try this, it works for me :)
Insert data >>>
const q = query(collection(this.fire, "events"));
const querySnapshot = await getDocs(q);
const queryData = querySnapshot.docs.map((details) => ({
...details.data(),
id: details.id,
}));
console.log(queryData);
queryData.map(async (v, id) => {
await setDoc(doc(this.fire, `events/${auth}/more`, events.title), {
'title': events.title,
'uid': auth,
//your data here
})
})
Read Data >>>
const querySnapshot = await getDocs(collection(this.fire,
`/events/${auth}/more/`)); querySnapshot.forEach((doc) => { //
doc.data() is never undefined for query doc snapshots
console.log(doc.id, " => ", doc.data()); });
return querySnapshot;

Trouble with "forEach" with Firebase Firestore .where() .get() Snapshots

I can only give an example of my code, since my real code is too big. I'm working with Firebase Cloud Functions and Firebase Firestore.
First I define a returnData dictionary (within my Firebase Cloud Function):
let returnData = {};
Then I get() "snapshots" of my db:
const db = admin.firestore();
const snapshotUsers = await db
.collection("users")
.where("followers", "array-contains", exampleId)
.get();
Then, I'm trying to populate the returnData dictionary:
snapshotUsers.forEach(async (docUsers) => {
await db
.collection("users")
.doc(docUsers.id)
.collection("profileProjects")
.listDocuments()
.then(async (documentRefsProjects) => {
if (!(Object.keys(documentRefsProjects).length === 0)) {
return await db.getAll(...documentRefsProjects);
}
})
.then(async (documentSnapshotsProjects) => {
if (!!documentSnapshotsProject) {
for (let documentSnapshotProject of documentSnapshotsProjects) {
if (documentSnapshotProject.exists) {
// ----------- Populate here -----------
returnData = {
...returnData,
[documentSnapshotProject.id]: {
followers: docUsers.data().followers,
}
};
// --------------------------------------
}
}
}
})
});
// Send response when forEach is done with returnData
res.status(201).send({ returnData: returnData });
Problem is: once it successfully populates returnData, it then throws that data away and
res.status(201).send({ returnData: returnData }); returns the initial empty dictionary
I understand that: "forEach() executes the callback function once for each array element; unlike map() or reduce() it always returns the value undefined and is not chainable", but I seems like I have no other option than to use forEach for firestore, so I'm stuck.
I tried using the map() function instead, but Firestore returns TypeError: snapshotUsers.map is not a function.
I even tried doing a manual for...in and for...of loop, but those also gave me errors when I would try to call id on docUsers:
for (let docUsers of snapshotUsers) {
await db
.collection("users")
.doc(snapshotUsers[docUsers].id) // <---- error'd here
I'm having a real tough time here since the only way I can test this is deploying the Firebase Cloud Function every time.
I wondering if anyone can help me out here. Any advice or solution helps.
I'm having a real tough time here since the only way I can test this is deploying the Firebase Cloud Function every time.
check it: https://firebase.google.com/docs/hosting/test-preview-deploy
I used to work with:
firebase serve --only functions
And it just work fine.
For your problem...
Your foreach is ending before your returnData is populated.
Foreach has one argument that show the current data index in your array.
So, in your success callback, you can check if it is the last array's data then just send your response.
Something like this:
let returnData;
xpto.forEach((data,index)=>{
db.then(()=>{
//populates your returnData
if(index === xpto.lenght-1) res.status(201).send({ returnData })
})
})
Edit with askers experience:
for some reason didn't work with the snapshots, I had to initialize an
index outside the forEach and increment it within the .then()
function.

Receiving undefined when retrieving value from firebase

Where is my call wrong? The first console.log leads to the role object and the second console.log leads to undefined. When it should be the user.
componentDidMount(){
let user = fire.auth().currentUser;
let db = fire.database();
let roleRef = db.ref('/roles');
roleRef.orderByChild('user').equalTo(user.uid).once('value', (snapshot) => {
console.log(snapshot.val())
console.log(snapshot.val().user);
})
}
Result:
Firebase:
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 doesn't take the list into account. The easiest way to do so is with Snapshot.forEach():
roleRef.orderByChild('user').equalTo(user.uid).once('value', (snapshot) => {
snapshof.forEach((roleSnapshot) => {
console.log(roleSnapshot.val())
console.log(roleSnapshot.val().user);
});
})

How to get the results of a query as an Object from Cloud Firestore?

I migrated from firebase Realtime Database to Cloud firestore in one of my ReactJS projects. And I am fairly new to Firestore.
Here's what I need. Consider that I have details of items stored in a collection 'Items'.
In Realtime database, I just had to do this to get the data and store it in the state:
database.ref('Items').once('value', (snapshot) => {
this.setState({items: snapshot.val()})
})
snapshot.val() returns all the objects in Items as a single object containing them. That makes it easy for me to render them in a table with Object.keys(this.state.items).map()
From what I know so far:
This is not the case with Firestore. Firestore returns an object that can only retrieve the data in the child only by iterating through each one of them.
So the best I could come up with was:
db.collection('Items').get().then(gotData)
gotData = (snapshot) => {
snapshot.forEach((item) => {
const item = {[item.id]: item.data()}
this.setState(previousState => ({
items : {...previousState.items, ...item}
}))
})
}
The problem with the above solution is that the state will get updated a number of times equal to the number of items in the collection. So I wonder if there is a better way to do it.
Almost there, you just want to put the empty object outside the iteration like so...
db.collection('Items').get().then(snap => {
const items = {}
snap.forEach(item => {
items[item.id] = item.data()
})
this.setState({items})
}
Or you could just map it, which I find easier to think about.
db
.collection('Items')
.get()
.then(collection => {
const items = collection.docs.map(item => {[item.id]: item.data()})
this.setState({ items })
})
Or you can use reduce to return an object containing all the items.
db
.collection('Items')
.get()
.then((collection) => {
const items = collection.docs.reduce((res, item) => ({...res, [item.id]: item.data()}), {});
this.setState({items})
})

Categories

Resources