When removing an item from my RTDB, my intention is to clean up user's likes if the item they like got removed.
With my data structure like so:
I am attempting to remove the nodes like this:
const updates = {};
//WORKS
updates[`/strains/${title}/`] = null;
updates[`/strainsMin/${title}/`] = null;
firebase
.database()
.ref('reviews')
.orderByChild('s')
.equalTo(title)
.once('value', snapshot => {
console.log(snapshot.val())
snapshot.forEach(child => {
console.log(child.key)
//WORKS
updates[`/reviews/${child.key}`] = null;
});
})
.then(() => {
firebase
.database()
.ref('userLikedStrains')
.orderByChild(title)
.equalTo(title)
.once('value', snapshot => {
console.log(snapshot.val() + 'likeylikeyyy')
snapshot.forEach(child => {
console.log(child.key)
//DOESNT WORK
updates[`/userLikedStrains/${child.key}/${title}`] = null;
});
firebase
.database()
.ref()
.update(updates);
})
For some reason this doesn't work. Is it because I am targeting a key (which is still a child?..)
I appreciate any help with this!
Cheers.
The code you shared is not writing anything back to the database yet. For that you need to call update after the loop.
Something like:
let ref = firebase
.database()
.ref('userLikedStrains');
ref.orderByChild(title)
.equalTo(title)
.once('value', snapshot => {
console.log(snapshot.val())
snapshot.forEach(child => {
console.log(child.key)
updates[`/userLikedStrains/${child.key}/${title}`] = null;
});
ref.update(updates);
})
Related
I'm building an app using react-native and react-native-firebase and i'm running into an issue while trying to implement a comment section.
My tree of data is currently like that :
collection(comments)/doc(currentUser.uid)/collection(userComments)/doc(commentCreatorID)
Within this doc commentCreatorID there is all the data i need. So basically the content, a timestamp...
For this part everything works perfectly but in order to havethe commentCreator's infos stick with his post, i need to grab them somewhere else.
The way i do that is taking the doc(commentCreatorID), as it is the uid of this user and ask firestore to give me the data from the document with this same id within my "users" collection.
Here is my code :
const [comments, setComments] = useState([])
const [commentsReady, setCommentsReady] = useState([])
useEffect(() => {
setComments([])
setLoading(true)
firestore()
.collection('comments')
.doc(auth().currentUser.uid)
.collection('userComments')
.get()
.then((snapshot) => {
let comments = snapshot.docs.map(doc => {
const data = doc.data()
const id = doc.id
return {id, ...data}
})
setComments(comments)
})
.then(() => {
comments.forEach(comment => {
firestore()
.collection("users")
.doc(comment.id)
.get()
.then((snapshot) => {
const data = snapshot.data()
setCommentsReady({comments, ...data})
})
})
})
console.log(commentsReady)
setLoading(false)
}, [handleScroll4])
This doesn't seem to works well as for now. My log throw an empty array right into my face..
I'm grabbing each comment correctly tho and even each user's data corresponding to their uids.
I can log them once ForEach have been done.
But for some reason i can't have them set to my state commentsReady.
Did i miss something ?
Thanks for your time
The setters that the useState function returns are async. Copying data from one state to another is also an antipattern. Try using effects.
const TT = () => {
const [comments, setComments] = useState([]);
const [userInfos, setUserInfos] = useState([]);
const commentsView = comments.map(comment => {
// Reactively merge each comment with the appropriate user info
});
useEffect(() => {
firestore()
.collection('comments')
.doc(auth().currentUser.uid)
.collection('userComments')
.get()
.then((snapshot) => {
let comments = snapshot.docs.map(doc => {
const data = doc.data()
const id = doc.id
return {id, ...data}
});
setComments(comments);
});
}, []);
useEffect(async () => {
// Maybe keep a cache of fetched user datas, but not sure how this is architected
const snapshots = await Promise.all(comments.map(comment => {
return firestore()
.collection("users")
.doc(comment.id)
.get();
}));
setUserInfos(snapshots.map(snap => snap.data()));
}, [comments]);
};
I have the following json structure:
Within "all" node I have an attribute "drinkId" and I'm trying to move it outside that child node bringing it one level up.
I'm trying to read the value without any luck
const cocktailRef= firebase
.database()
.ref("Ratings");
cocktailRef.once("value", (snapshot) => {
snapshot.forEach((child) => {
const drinkIdPass = child.ref.child("all").child("drinkId").value();
child.ref.update({ drinkId: drinkIdPass });
})
})
I've tried different variants of ".value()", same problem
There isn't any value() method on a DataSnapshot. It's val() Try refactoring your code like this:
const cocktailRef= firebase.database().ref("Ratings");
cocktailRef.once("value").then(async (snapshot) => {
const updates = { }
snapshot.forEach((child) => {
const drinkIdPass = child.val().all.drinkId
updates[`${child.key}/drinkId`] = drinkIdPass
})
await cocktailRef.update(updates)
console.log("Data updated")
})
I need help, i'm trying to update my comments collections using cloud function, but my code doesn't seem to work. My function succesfully run but doesn't update my avatarUrl when my userPhotoUrl is update
Here the whole path of the collection that i want to update : "/comments/{postId}/comments/{commentId}"
my firestore collection
exports.onUpdateUser2 = functions.firestore
.document("/users/{userId}")
.onUpdate(async (change, context) => {
const userUpdate = change.after.data();
const userId = context.params.userId;
const newPhotoUrl = userUpdate.photoUrl;
console.log("userId",userId);
console.log("newPhotoUrl",newPhotoUrl);
const querySnapshot = await admin.firestore().collection("comments").get();
querySnapshot.forEach(doc => {
console.log("doc",doc.data());
const postId = doc.id;
const comments = admin.firestore().collection("comments").doc(postId).collection("comments").where("userId","==",userId).get();
comments.forEach(doc2 => {
return doc2.ref.update({avatarUrl: newPhotoUrl});
});
});
});
Thank you,
UPDATE
I try to change the code, by using then to deal with these various promises but i don't really know why commentsRef.get() seem to return me empty querySnapshots, because the comments collections in my firestore database have multiple documents where in each documents there is a another comments collections where in this seconds comments collections there is a bunch of documents containing data. With this whole path i don't know how to iterate until being in the documents containing the data that i need to update. Can someone help me please ?
exports.onUpdateUserUpdateComments = functions.firestore
.document("/users/{userId}")
.onUpdate(async (change, context) => {
const userUpdate = change.after.data();
const userId = context.params.userId;
const newPhotoUrl = userUpdate.photoUrl;
console.log("userId",userId);
console.log("newPhotoUrl",newPhotoUrl);
const commentsRef= admin.firestore().collection("comments");
return commentsRef.get().then(querySnapshot => {
return querySnapshot.forEach(doc => {
return admin
.firestore()
.collection("comments")
.doc(postId)
.collection("comments")
.where("userId", "==", userId)
.get()
.then(doc => {
if (doc.exists) {
doc.ref.update({avatarUrl: newPhotoUrl});
}
return console.log("The function has been run.");
});
});
});
});
Without trying it, it should be something like this:
return admin.firestore().collection("comments")
.doc(postId)
.where("userId", "==", userId)
.get()
.then(doc => {
if (doc.exists) {
doc.ref.update({avatarUrl: newPhotoUrl});
}
return console.log("The function has been run.");
});
Regardless, following Doug Stevenson's advice, you shouldn't start learning JS in Cloud Functions, as those nested loops are a bit strange and you may lack a good starting point for learning.
I would like to check/compare if a value is inside this data:
example:
const uid = '35nv594aotgcv'
#check if uid is inside
firebase
.database()
.ref('followers/2mvouwB0E0aEN5MnAhOLWaHiu6b2')
.once("value", snapshot => {
if (snapshot.exists()) {
const data = snapshot.val(); // data are the other two uid's in the image above
}
});
So how can I check if the const uid = '35nv594aotgcv' is inside the snapshot data?
or if I have an Array with uid's like const uids = ['234', '343', '3242', ...]
If I understand you correctly, you're looking for DataSnapshot.hasChild(). With that you can check whether the snapshot has a certain child node.
Something like:
firebase
.database()
.ref('followers/2mvouwB0E0aEN5MnAhOLWaHiu6b2')
.once("value", snapshot => {
if (snapshot.hasChild('35nv594aotgcv')) {
console.log('Yes');
}
});
I am succesfully updating my user's profile picture on their profile and on all of their reviews posted with this function:
export const storeUserProfileImage = (url) => {
const { currentUser } = firebase.auth();
firebase.database().ref(`/users/${currentUser.uid}/profilePic`)
.update({ url });
firebase.database().ref('reviews')
.orderByChild('username')
.equalTo('User3')
.once('value', (snapshot) => {
snapshot.forEach((child) => {
child.ref.update({ profilePic: url });
});
});
};
I am aware that I should be using an atomic update to do this so the data updates at the same time (in case a user leaves the app or something else goes wrong). I am confused on how I can accomplish this when querying over child values.
Any help or guidance would be greatly appreciated!
Declare a variable to store all the updates. Add the updates as you read them on your listener's loop. When the loop is finished, run the atomic update.
export const storeUserProfileImage = (url) => {
const { currentUser } = firebase.auth();
firebase.database().ref('reviews')
.orderByChild('username')
.equalTo('User3')
.once('value', (snapshot) => {
var updates = {};
updates[`/users/${currentUser.uid}/profilePic`] = url;
snapshot.forEach((child) => {
updates[`/reviews/${child.key}/profilePic`] = url;
});
firebase.database().ref().update(updates);
});
};