Reputation:
I need help with something.
I have 2 collections on my project, one is called Products and another called Users.
I’m duplicating the selected product information into a sub-collection of users as favorites, in this case:
users(collection) > user(doc) > favorites(collection) > product (doc)
My idea is to create a cloud-function that will watch for any updates on any product in the "product collection" product(collection) > product(doc) and then reflect those changes on the users > favorites sub-collection by updating the values of the products here:
users(collection) > user(doc) > favorites(collection) > product (doc)
How is this possible from index.js ? This my code:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
exports.updateFavoritedProducts = functions.firestore.document('products/{productId}').onUpdate((change, context) => {
admin.firestore().collection('products').get(queryProductsSnapshot => {
queryProductsSnapshot.forEach(productQuery => {
const pricePQ = productQuery.price;
console.log('tetesfsf');
return admin.firestore().collection('users').get(queryUsersSnapshot => {
queryUsersSnapshot.forEach(userSnapshot => {
return admin.firestore().collection('users').doc(userSnapshot.id).collection('favorites').get(queryUserProductsSnapshot => {
queryUserProductsSnapshot.forEach(queryUserProductSnapshot => {
if (queryUserProductSnapshot.id === productQuery.id) {
return admin.firestore().doc(`users/${userSnapshot.id}/favorites/${queryUserProductSnapshot.id}`).update({ amountVolume: '123456'
})
} else {
console.log("No events found");
return null
}
})
});
})
})
});
})
});
Upvotes: 2
Views: 3218
Reputation: 1114
I used user1889692's answer to update all the documents in a even deeply nested sub-collection in my project.
timeline(collection) > timeline(doc) > publisherId(collection) > publisherIdId(doc) > posts(collection) > postId(doc)
This is my working code:
exports.onCreateTimelineTest = functions.firestore
.document("/timelineTest/{buguId}")
.onCreate(async (snapshot, context) => {
const timeNow =new Date();
const db = admin.firestore();
return db.collection("timeline")
.get()
.then((timelineQuerySnapshot) => {
timelineQuerySnapshot.forEach(async(timelineQuerySnapshot) => {
console.log("all the documnets inside timeline are", timelineQuerySnapshot.id);
await db.collection("timeline")
.doc(timelineQuerySnapshot.id)
.collection("publisherId")
.get()
.then((publisherSnapshot)=>{
publisherSnapshot.forEach(async(publisherSnapshot)=>{
console.log("all the documnets inside timeline are", publisherSnapshot.id);
await db.collection("timeline")
.doc(timelineQuerySnapshot.id)
.collection("publisherId")
.doc(publisherSnapshot.id)
.collection("posts")
.where('uploadTime', '<=', timeNow)
.get()
.then((postSnap)=>{
postSnap.forEach(async(postSnap)=>{
console.log("all the documnets inside timeline are", postSnap.id);
return db.collection("timeline")
.doc(timelineQuerySnapshot.id)
.collection("publisherId")
.doc(publisherSnapshot.id)
.collection("posts")
.doc(postSnap.id)
.set({
'name': 'madhav'
}).catch((err)=>{
console.log('Error getting documents', err);
return Promise.reject(err);
});
});
return null
}).catch((err) => {
console.log('Error getting documents', err);
return Promise.reject(err);
});
});
return null
}).catch((err) => {
console.log('Error getting documents', err);
return Promise.reject(err);
});
});
return null
}).catch((err) => {
console.log('Error getting documents', err);
return Promise.reject(err);
});
});
Upvotes: 0
Reputation:
I finally figured out how to do this with nesting promises. Here is the solution:
exports.updateFavoritedProducts = functions.firestore.document('products/{productId}').onUpdate((change, context) => {
const data = change.after.data();
const productID = data.id;
return db.collection('products').where('id', '==', productID).get().then((productsQuerySnap) => {
productsQuerySnap.forEach((productQuerySnap) => {
const newPrice = productQuerySnap.data().price;
const newPriceUnit = productQuerySnap.data().priceUnit;
db.collection('users').get().then((usersQuerySnap) => {
usersQuerySnap.forEach((userQuerySnap) => {
return db.collection('users').doc(userQuerySnap.id).collection('favorites').doc(productQuerySnap.id).update({
price: newPrice,
priceUnit : newPriceUnit
}).catch((err) => {
console.log('Error getting documents', err);
return Promise.reject(err);
});
});
return null
})
.catch((err) => {
console.log('Error getting documents', err);
return Promise.reject(err);
});
return null
});
return null
})
.catch((err) => {
console.log('Error getting documents', err);
return Promise.reject(err);
});
});
Upvotes: 1
Reputation: 598708
If you want to create a Cloud Function that triggers on all product updates for all users, you declare it as:
functions.firestore.document('users/{userId}/products/{productId}').onUpdate((change, context) => {
If you then want to access userId
or productId
inside the function body, you can get them as:
context.params.userId
context.params.productId
Upvotes: 4