How to make array by checking object property in firebase? - javascript

I have a list of users in firebase database and I want to make an array of all users whose isDonor value is true. How can I accomplish that?

Something like this should work:
let ref = firebase.database().ref("users");
ref.orderByChild("isDonor").equalTo(true).once("value").then((results) => {
results.forEach((snapshot) => {
console.log(snapshot.key, snapshot.val());
});
});
Also see the Firebase documentation on sorting and filtering data.

Related

How to search for specific fields in an array of objects containing objects in a document and update them in firestore (firebase) (JS)

// Update the other user that current user has asked for revision
export async function updateOtherUserForContractRevision(contractID : string, comments : any) {
// getting userDetails
let currentUser : string | any = localStorage.getItem("userDetails");
currentUser = JSON.parse(currentUser);
// update fields in contractRecieved
const contractsRecievedRef : any = doc(db, "contractsRecieved", currentUser.uid);
// const queryContractsRecieved = query(contractsRecievedRef,
// where('contractDetails.contract.contractID','array-contains',contractID)
// );
// console.log(".////////updateOtherUserForContractRevision", queryContractsRecieved ,contractID)
onSnapshot(contractsRecievedRef, (doc: any) => {
doc.data().contract.map((contract: any) => {
if(contract.contractDetails.contract.contractID === contractID) {
// I reach my desired array Index and want to update the msg field to my comments parametre
console.log(".////////contract", contract);
}
})
})
}
I want to update my msg field as well as content field in contract object, which in turn is present in contractDetails object in the contract array(0th index). I have searched and reached to my desired array value using onSnapShot, how can I update these fields in the onSnapShot method? or I should use another approach for searching and updating fields in objects contained by the array.
JUST A THOUGHT: If I could get the reference to the array index and then use it to update the object, maybe It'll work
for example (I'll update sentForRevision)
onSnapshot(contractsRecievedRef, async (doc: any) => {
doc.data().contract.map(async (contract: any) => {
if(contract.contractDetails.contract.contractID === contractID) {
console.log(".////////contract", doc.ref);
// If this contract.ref exists and points to the index present in the document
await updateDoc(contract.ref,{
"contractDetails.sentForRevision": true,
});
}
})
})
There is no way you can query a Firestore collection based on a value that exists in an object that is contained in an array. This kind of filtering cannot be achieved using partial data. I have even written an article regarding this topic called:
How to update an array of objects in Firestore?
If you need that, you can duplicate the data on which you want to perform the filtering and add it to a separate array. In this way, you can query the collection using array-contains operator. Once you get the desired documents, you can get the array, perform the updates and then write the documents back to Firestore.

Firebase orderByKey().startAt() not working as expected. What's wrong?

I'm trying to get firebase data from a node which uid must start with a passed string.
I tried a code but I always get the same data. The database data is as following:
And I'm using the following code:
var ref = firebase.database().ref("restaurantes/history");
ref.orderByKey().startAt(userUID).once("child_added", function(snapshot) {
snapshot.forEach(child => {
if(child.key == "orders")
{
console.log(child.val());
_.each(child.val(), (value, key) => {
arrtmp.push(value)
})
}
})
If user is "FKQLlqa" I should get the history data shown in the picture. If I user is "abc" I shouldn't get any data. But I always get the data shown in the picture. Should I use another way of querying? Or I should use a key field inside orders and payments data?
Regards!
Try the following:
var ref = firebase.database().ref("restaurantes/history");
ref.child(userUID).once("value", function(snapshot) {
if (snapshot.exists()) {
console.log(snapshot.val());
}
else {
console.log("different user");
});
This will check if the snapshot that contains the userId (added as a parameter in the child() method), already exists in the database then you will be able to retrieve the data under the userId.
For reference:
https://firebase.google.com/docs/reference/js/firebase.database.DataSnapshot#exists
Peter's answer is the correct solution. I'm merely adding this for completeness.
When you call orderBy... on a Firebase reference, the database orders all child nodes on the key/value/child that you specify.
If you then subsequently call startAt(...) on the query, it finds the (first) node that starts with that value and starts returning all results from there. So if you start at FKQLlqa, it will start returning keys at FKQLlqa and then return all keys after it.
If you want to return the child node(s) with a specific key/value/child, you'd use equalTo(...). So:
ref.orderByKey().equalTo(userUID).once("child_added", function(snapshot) {
...
But as Peter said already, this is just a more expensive way to look up a child with a known key. I highly recommend using his better approach: ref.child(userUID).once("value".

How to push an array value in Firebase Firestore

I am trying to push an array element but am destroying all the content there and replacing with the pushed data:
db .collection('households')
.doc(householdId)
.set( { users: [uid], }, { merge: true }, )
.then(() => { resolve(); })
.catch(() => reject());
I thought the merge true doesn't destroy the data that is already there? Struggling a little with the firestore api docs.
This is the structure of my data:
households
2435djgnfk
users [
0: user1
1: user2
]
Thank you!
You should use Firestore Transaction for this.
const householdRef = db.collection('households').doc(householdId);
const newUid = '1234'; // whatever the uid is...
return db.runTransaction((t) => {
return t.get(householdRef).then((doc) => {
// doc doesn't exist; can't update
if (!doc.exists) return;
// update the users array after getting it from Firestore.
const newUserArray = doc.get('users').push(newUid);
t.set(householdRef, { users: newUserArray }, { merge: true });
});
}).catch(console.log);
Updating an array or a stored object without getting it first will always destroy the older values inside that array/object in firestore.
This is because they are fields and not actual document themselves. So, you have to first get the document and then update the value after that.
I think now you can do it better with the update command on document by using FieldValue.arrayUnion without destroying data that was added meanwhile. Like this:
const admin = require('firebase-admin');
let db = admin.firestore();
const FieldValue = admin.firestore.FieldValue;
let collectionRef = db.collection(collection);
let ref = collectionRef.doc(id);
let setWithOptions = ref.update(arrayFieldName, FieldValue.arrayUnion(value));
As described in https://firebase.googleblog.com/2018/08/better-arrays-in-cloud-firestore.html
Arrays in Firestore don't work like this. According to the documentation:
Although Cloud Firestore can store arrays, it does not support querying array members or updating single array elements.
If you want to change any element in an array, you have to read the array values from the document first, make changes to it in the client, then write the entire array back out.
There are probably other ways to model your data that are better for your use case. That page of documentation linked above has some solutions.

JavaScript Firebase: Query Snapshot Always Null

No matter what I do I can't seem to figure out a way to access the child "onSite", which shows as being there when I log snapshot.val(), but I cannot figure out how to access it.
Code:
firebase.database().ref().child("users").orderByChild('facebook_id').equalTo(fbID).once("value").then(function(snapshot) {
console.log(snapshot.val());
console.log(snapshot.child("onSite").val());
});
Here is the response:
It shouldn't be null, it should be false. I can't do child("4mUUjF...").child("onSite").val() because I don't know what the ID is before the query. Using an each loop doesn't work, it only loops through the first level, which is the ID.
Use the key of the object
Get the snapshot val and then find the key with the Object.keys method. This will allow you to then get inside the snap. Once there it's a simple matter of accessing the values like any other object.
firebase.database().ref().child("users").orderByChild('facebook_id').equalTo(fbID).once("value").then(function(snapshot) {
let snap = snapshot.val();
let key = Object.keys(snap)[0]
console.log(snap[key].onSite);
})
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 handle the list, by using Snapshot.forEach():
firebase.database().ref().child("users").orderByChild('facebook_id').equalTo(fbID)
.once("value").then(function(result) {
result.forEach(function(snapshot) {
console.log(snapshot.val());
console.log(snapshot.child("onSite").val());
});
});

How to ready key and value from firebase db collection

I have following db structure in firebase. I want to retrieve this collection and display using ngFor in my view. However I want read Key (which firebase generates when we use push method) of each object to use it later.
I am retrieving data like this.
this.dbref = firebase.database().ref('My top node here');
this.dbref.once('value').then(snapshot => this.myProperty = snapshot.val());
if I log myProperty I can see object collection along with Keys like this but I don't know a way to read key associated with each object. Can someone help?
I think you're looking for:
this.dbref = firebase.database().ref('My top node here');
this.dbref.once('value').then(snapshot => {
this.myProperty = snapshot.val();
snapshot.forEach(child => {
console.log(child.key, child.val());
});
})

Categories