How to add Dummy Data in Firestore using cloud functions

Viewed 956

I want to add dummy values in firestore using cloud functions and im using http trigger to pass the number of dummy values that i want to create, this doesnt work

exports.addDummyUsers = functions.https
.onRequest((request,response)=>{

    let dbb=admin.firestore();
    let counter = request.query.counter;

     for(let i=0;i<counter;i++){
        dbb.collection('Users').doc('Lone').set({
            email: 'Dummy',
            name: 'Dummy',
            phoneNumber: 'Dummy'
        });
        console.log("Dummy " + counter + ' added');
     }

    response.send(counter + ' Dummy Values Created!');
});
2 Answers

Updated Answer following Frank's comment below:

You want to create several Firestore documents in parallel. In your case (no need for an atomic write) the best is to use Promise.all().

You should wait that the set of asynchronous operations is completed before sending back the response, i.e. wait that the single Promise returned by Promise.all() resolves.

So, the following should work:

exports.addDummyUsers = functions.https.onRequest((request, response) => {

        let dbb = admin.firestore();
        let counter = request.query.counter;

        const promises = []

        for (let i = 0; i < counter; i++) {
            promises.push(
                dbb.collection('Users').doc('Lone' + i).set({
                    email: 'Dummy',
                    name: 'Dummy',
                    phoneNumber: 'Dummy'
                })
            )
        }

        return Promise.all(promises)
            .then(resultsArray => {
                response.send(counter + ' Dummy Values Created!');
            })
            .catch(error => {

               //Watch the official video: https://www.youtube.com/watch?v=7IkUgCLr5oA&t=1s&list=PLl-K7zZEsYLkPZHe41m4jfAxUi0JjLgSM&index=3

            });

});

Original answer:

See Frank's comment below on why it is better to use Promise.all() in any case.

See also the following remark in the doc: "...Batched writes perform better than serialized writes but not better than parallel writes.

You should either use a batched write (if you have less than 500 documents to write) or use Promise.all().

You should also wait that the set of asynchronous operations is completed before sending back the response.

So the following should work:

exports.addDummyUsers = functions.https.onRequest((request, response) => {

    let dbb = admin.firestore();
    let counter = request.query.counter;

    if (counter < 500) {
        //Use batched write
        let batch = dbb.batch();

        for (let i = 0; i < counter; i++) {

            const docRef = dbb.collection('Users').doc('Lone' + i);  //Here you need to create different doc reference. E.g. use the value of i
            batch.set(docRef, {
                email: 'Dummy',
                name: 'Dummy',
                phoneNumber: 'Dummy'
            });
        }

        return batch.commit()
            .then(() => {
                response.send(counter + ' Dummy Values Created!');
            })
            .catch(error => {
                //Watch the official video: https://www.youtube.com/watch?v=7IkUgCLr5oA&t=1s&list=PLl-K7zZEsYLkPZHe41m4jfAxUi0JjLgSM&index=3
            });


    } else {
        //Use Promise.all
        const promises = []

        for (let i = 0; i < counter; i++) {
            promises.push(
                dbb.collection('Users').doc('Lone' + i).set({
                    email: 'Dummy',
                    name: 'Dummy',
                    phoneNumber: 'Dummy'
                })
            )
        }

        return Promise.all(promises)
            .then(resultsArray => {
                response.send(counter + ' Dummy Values Created!');
            })
            .catch(error => {

                //Watch the official video

            });

    }

});

Renauds answer is good and complete but just to simplify everything a bit, the following will work but will possibly timeout depending on the value of the counter.

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

exports.addDummyUsers = functions.https.onRequest(async (request,response)=>{

let dbb=admin.firestore();
let counter = request.query.counter;
let userName = ""

for(let i=0;i<counter;i++){

    userName = "Lone" + i.toString().padStart(4, '0') // pad to length 4 with leading zeros
    await dbb.collection('Users').doc(userName).set({
        email: 'Dummy',
        name: 'Dummy',
        phoneNumber: 'Dummy'
    });
    console.log("Dummy " + counter + ' added');
 }

response.send(counter + ' Dummy Values Created!');
});

The problems in your code are as follows:

In the line dbb.collection('Users').doc('Lone').set({

you do not add i to to doc name so you keep overwriting the same doc "Lone". Renaud fixed this.

Secondly there is no await, so the cloud function will finish before the documents are added so some of the documents will not be added. The async in the

exports.addDummyUsers = functions.https.onRequest(async (request,response)=>{

then means you can use await and this means that the code will wait until each document has been added. this is much more efficient if you do batch writes but as Renaud pointed out, 500 writes (or the combination of adds, updates or deletes) is the limit.

You could also do the same by doing the batch writes inside a loop if counter is greater than 500.

Also, to make the sorting look more logical in the firebase console, I have padded the counter value to 4 (obviously this would not be enough if the counter was passed as 10000)

To change the timeout do the following

This is by default set to 60 seconds on cloud functions although this can be changed by using runWith and the timeout and memory options if you need to increase runtime memory.

const runtimeOpts = {
  timeoutSeconds: 300,
  memory: '1GB'
}

exports.addFirestoreData = functions.wunWith(runtimeOpts).https.onCall(async data => {

One other note. You need to be careful that you do not create hotspots in your data by not using automatically generated document ids.

Your users are going to be all in the same area as the names are all Lone0001,Lone002 etc. which will mean that accesses will clash a lot and therefore reduce performance.

The point of the automatically generated document Ids is that they are designed to avoid hotspots. This discusses best practices https://cloud.google.com/firestore/docs/best-practices

Related