I'm trying do display data from Firestore database in my component.
This is my function:
const getData = async () => {
const data = [];
const querySnapshot = await getDocs(
collection(databaseRef, "mK7DFNJgRAPmtvgrZh7X6AOj8cR2")
);
console.log(querySnapshot);
querySnapshot.forEach((doc) => {
console.log(doc.id, " => ", doc.data().Title);
data.push({
About: doc.data().About,
Title: doc.data().Title,
Who: doc.data().Who,
});
});
setData(data);
};
Collection ID = Current logged in User.
I want to display every document.
Everything works fine but insteed of passing hard-coded string here:
collection(databaseRef, "mK7DFNJgRAPmtvgrZh7X6AOj8cR2")
I would like to pass variable where I store my UID.
Is there any way to do that?
Assuming your user is logged in, you should be able to access their UID via firebase.auth().currentUser.uid. This question's answers may be useful for more information on getting the current user's ID.
With that, you should be able to do:
const querySnapshot = await getDocs(
collection(databaseRef, firebase.auth().currentUser.uid)
);
to get the current user's documents.
https://firebase.google.com/docs/reference/js/v8/firebase.auth.Auth#currentuser
Related
I am creating a database for the products. The products are pushed into the database successfully but I am facing a problem in getting the data because the keys are nested. How can I target the nested key?
Please help me.
Using the below code I am getting my all the products data of currently logged in user.
useEffect(() => {
const getProductsData = async () => {
const userId = await AsyncStorage.getItem('uid')
database()
.ref(`Products/${userId}`)
.on('value', data => {
console.log(data.val())
});
}
getProductsData()
}, [])
console of the data.val()
Assuming that your userId is the dUD7M... value in the screenshot you shared, the data snapshot you get will contain the data for both child nodes in that screenshot. You can loop over those children with:
const userId = await AsyncStorage.getItem('uid')
database()
.ref(`Products/${userId}`)
.on('value', snapshot => {
snapshot.forEach((data) => { // 👈
console.log(data.val())
});
});
I'm trying to retrieve all the collections inside of all the documents of a collection called users.
This is how I retrieve all the users.
export async function getServerSideProps() {
const snapshot = await firebase
.firestore()
.collection("users")
.orderBy("points", "desc")
.get();
let users = snapshot.docs.map((doc) => doc.data());
...
}
What I want, is to get the collections inside those users and save them into an array.
Firestore
I want to retrieve the all the "quiniela" collections from all the users and pass them as props
Is there a way to do this?
You need to load the quiniela collection from each document with .collection().
let users = snapshot.docs.map(async (user) => {
let quiniela = (await user
.collection("quiniela")
.get())
.map((doc) => doc.data());
return {
...user.data(),
quiniela,
}
});
This should add the document data from the user's quiniela collection.
Note that users will now be a Promise[]. If you need to load the data, call:
await Promise.all(users)
here's the basic premise of what im trying to accomplish here. if a user ask a question about a product i want to send a notification to other users who currently own that product. basically saying "hey, so and so has a question about this product. maybe you can help since you own it already"
each userProfile collection has a subcollection called 'notify' where notifications are stored for various things. what i need to do is sort through the userProducts and find every user who owns the product and then create a notification post in only the notify sub-collections for those specific users who own that product.
here is the basic code. the first bit works in that it does return an array of userIDs who own that product. where im struggling now is getting it to create a new doc in the Notify sub-collection for just those specific users. is this possible to do?
exports.Questions = functions.firestore
.document("/userPost/{id}")
.onCreate(async (snap, context) => {
const data = snap.data();
if (data.question == true) {
const userProducts = await db
.collection("userProducts")
.where("product", "==", data.tag)
.get();
const userData = userProducts.docs.map((doc) => doc.data().userId);
await db
.collection("userProfile")
.where("userId", "in", userData)
.get()
.then((querySnapshot) => {
return querySnapshot.docs.ref.collection("notify").add({
message: "a user has asked about a product you own",
});
});
});
Your current solution is on the right track, but there are improvements that can be made.
Use a guard pattern for the data.question == true check.
You don't need to get userProfile/<uid> as you aren't using its contents.
When changing multiple documents at once, you should consider batching them together for simpler error handling.
ref.add(data) is shorthand for ref.doc().set(data) which you can use in the batched write to create new documents.
exports.Questions = functions.firestore
.document("/userPost/{id}")
.onCreate(async (snap, context) => {
const data = snap.data();
if (!data.question) {
console.log("New post not a question. Ignored.")
return;
}
const userProducts = await db
.collection("userProducts")
.where("product", "==", data.tag)
.get();
const userIds = userProducts.docs.map(doc => doc.get("userId")); // more efficient than doc.data().userId
// WARNING: Limited to 500 writes at once.
// If handling more than 500 entries, split into groups.
const batch = db.batch();
const notificationContent = {
message: "a user has asked about a product you own",
};
userIds.forEach(uid => {
// creates a ref to a new document under "userProfile/<uid>/notify"
const notifyDocRef = db.collection(`userProfile/${uid}/notify`).doc();
batch.set(notifyDocRef, notificationContent);
});
await batch.commit(); // write changes to Firestore
});
Note: There is no special handling here for when no one has bought a product before. Consider pinging the product's owner too.
Hello I want to update a field in a firebase document.
Right now , I am accessing the document collection like this
However I am having trouble setting teh shares field of the doc to shares+=1 ?
What am i doing wrong here in the set method?
const buyStock = async () => {
const q = await query(
collection(db, 'myStocks'),
where('ticker', '==', props.name)
);
const querySnapshot = await getDocs(q);
if (!querySnapshot.empty) {
// simply update the record
querySnapshot.forEach((doc) => {
doc.id.set({
shares: doc.id.data().shares+=1
})
// doc.data() is never undefined for query doc snapshots
console.log(doc, doc.id, ' => ', doc.data());
});
You're almost there. To update a document, you need a reference to that document. You can get this with:
querySnapshot.forEach((doc) => {
doc.ref.update({
shares: doc.data().shares+=1
})
});
You can also use the built-in atomic increment operator:
doc.ref.update({
shares: increment(1)
})
It looks like you are calling the set method on the 'id' field. Try to remove that. So just do
doc.set({
shares: doc.data().shares+=1
})
give that a shot. If that doesn't work, i'd try updating a document that is not part of a query snapshot.
yeap, if read a title you can think that it is simple action via collection - but no -> in you we have a button "Add collection": not clear how to add this collection via code or how to receive these created collections.
Please take a look at the structure of BD in the attachment:
.
I can receive ID of a document, but not clear how to receive collection(s)/data of these collections. here i just receive the main ID, not "1" collection and his data:
const listCollections = [];
await db
.collection(table)
.get()
.then((snapshot) => {
snapshot.docs.forEach((doc) => {
debugger
const dataCollectionObject = doc.data();
dataCollectionObject.id = doc.id;
listCollections.push(dataCollectionObject);
});
});
When you receive a document, you need another query to inspect its sub-collections.
Also, I suggest not mixing async/await with then.
A basic approach
const rootSnapshot = await db.collection(table).get();
const promises = rootSnapshot.docs.map(rootDoc => rootDoc.ref.collection("1").get());
const childrenDoc = await Promise.all(promises);
Using collection group queries
see the doc
const childrenDoc = await db.collectionGroup("1").get();
If you do not know the sub-collection name
Bad luck! With Firestore you are required to know the name of your collections. You could for exemple store it in another data member:
document {
someField: ...
collectionIds: ["1", "2"] // store the sub-collection ids
"1" // a sub-collection
"2" // another sub-collection
}
Then when you retrieve such a document, inspect its data and loop on collectionIds to query deeper.