-1

I have this architecture in my firestore: test1/{test1ID}/test2/

I want to interact with my firestore in cloud functions whenever new data is added to test1ID.

My goal is to update the test1ID document where data is updated, with the value of [0]th + [1]th + [2]th document under subcollection test2.

But with the code below I get test2 document list(currentTest2DocumentList) undefined.

(error message => TypeError: Cannot read property '0' of undefined)

How can I get a valid list of documents under subcollection?

const functions = require('firebase-functions');
const admin = require('firebase-admin');

admin.initializeApp();

exports.onItemDocumentUpdate = functions.firestore.document('test1/{test1ID}')
.onUpdate(async (change, context) => {

const currentTest1ID = context.params.test1ID


const currentTest2DocumentList = await 
admin.firestore().collection('test1').doc(currentTest1ID).collection('test2').get()
.then(function(docs) {return docs.forEach(function (doc){doc.data()})})

const addedValue = currentTest2DocumentList[0].field1 + currentTest2DocumentList[1].field1 + 
currentTest2DocumentList[2].field1

return admin.firestore().collection('test1').doc(currentTest1ID).update({testField: 
addedValue});
Andy Young
  • 39
  • 5

3 Answers3

1

You dont seem to use forEach properly. Try this:

const currentTest2DocumentList = await
admin.firestore().collection('test1').doc(currentTest1ID).collection('test2').get()
.then(function(docs) {
  let res = []
  docs.forEach(doc => res.push(doc.data()));
  return res;
})

Or even better:

const currentTest2DocumentList = await
admin.firestore().collection('test1').doc(currentTest1ID).collection('test2').get()
.then(docs => docs.map(doc => doc.data()));

Do you have more than 3 documents in the test2 collection? Because then it seems a waste to read all of them. You can add limit(3) to fix this

const currentTest2DocumentList = await
admin.firestore().collection('test1').doc(currentTest1ID).collection('test2').limit(3).get()
.then(docs => docs.map(doc => doc.data()));
l1b3rty
  • 3,333
  • 14
  • 32
0

This line of code isn't doing what you expect:

const currentTest1ID = context.params.ID

I suggest logging currentTest1ID. It will be undefined. That's because context.params only contains keys that are marked by wildcards in the document path. You don't have any wildcard called "ID". Perhaps this is what you want:

const currentTest1ID = context.params.test1ID

Note that test1ID matches the wildcard you defined in the function path.

Doug Stevenson
  • 297,357
  • 32
  • 422
  • 441
  • Oh thank you for the correction. I edited the Question. I made a mistake when making a question for StackOverflow but even with the corrected question 'currentTest2DocumentList' still gives unidentified. Any suggestions on it? – Andy Young Aug 04 '20 at 06:22
0

The reason why it is returning undefined is that the forEach function does not return any values. Try accessing the docs field of the collection snapshot and using the javascript map function like so:

// IMPORT
const functions = require('firebase-functions');
const admin = require('firebase-admin');

// INIT
admin.initializeApp();

// LISTEN TO UPDATES
exports.onItemDocumentUpdate = functions.firestore.document('test1/{test1ID}').onUpdate(async (change, context) => {
    // GETS PARAMS
    const currentTest1ID = context.params.test1ID

    // READ THE COLLECTION
    const currentTest2DocumentList = await admin.firestore().collection('test1/' + currentTest1ID + '/test2').get().then(function(collectionSnapShot) {
        return collectionSnapShot.docs.map(function (doc){
            return doc.data();
        })
    })

    // GETS THE SUM USING THE REDUCE METHOD.
    const addedValue = currentTest2DocumentList.reduce((x,y)=>{
        return x + y.field1;
    }, 0);

    // UPDATES TEST.
    return admin.firestore().collection('test1').doc(currentTest1ID).update({testField: 
        addedValue
    });
})

May I also suggest using the increment and decrement solution like so in my answer to reduce document read? It will save you a lot in your monthly bills.

CRUD DS
  • 456
  • 2
  • 5