Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

firebase firestore addding new document inside a transaction - transaction.add is not a function

I was assuming that it was possible to do something like:

transaction.add(collectionRef,{
  uid: userId,
  name: name,
  fsTimestamp: firebase.firestore.Timestamp.now(),
});

But apparently it is not:

transaction.add is not a function

The above message is displayed inside the chrome console.

I see that we can use the set method of the transaction to add a new document transactionally. see: https://firebase.google.com/docs/firestore/manage-data/transactions

The thing is if I use set instead of add(which is not supported anyways), the id of the document should be created by me manually, firestore won't create it. see: https://firebase.google.com/docs/firestore/manage-data/add-data

Do you see any downside of this not having an add method that generates the id for you automatically?

For example, is it possible that the id generated by the firestore itself is somehow optimized considering various concerns including performance?

Which library/method do you use to create your document IDs in react-native while using transaction.set?

Thanks

like image 426
honor Avatar asked Apr 14 '19 10:04

honor


People also ask

What is the maximum documents that are write by per transaction or batch of write in cloud firestore?

Each transaction or batch of writes can write to a maximum of 500 documents.

Can two documents have the same ID in firestore?

New document with same ID should not be allowed in the same collection. It should be possible to fetch an already existing document from a previous import.


3 Answers

If you want to generate a unique ID for later use in creating a document in a transaction, all you have to do is use CollectionReference.doc() with no parameters to generate a DocumentReference which you can set() later in a transaction.

(What you're proposing in your answer is way more work for the same effect.)

// Create a reference to a document that doesn't exist yet, it has a random id
const newDocRef = db.collection('coll').doc();

// Then, later in a transaction:
transaction.set(newDocRef, { ... });
like image 129
Doug Stevenson Avatar answered Oct 19 '22 10:10

Doug Stevenson


after some more digging I found in the source code of the firestore itself the below class/method for id generation:

export class AutoId {
  static newId(): string {
    // Alphanumeric characters
    const chars =
      'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    let autoId = '';
    for (let i = 0; i < 20; i++) {
      autoId += chars.charAt(Math.floor(Math.random() * chars.length));
    }
    assert(autoId.length === 20, 'Invalid auto ID: ' + autoId);
    return autoId;
  }
}

see: https://github.com/firebase/firebase-js-sdk/blob/73a586c92afe3f39a844b2be86086fddb6877bb7/packages/firestore/src/util/misc.ts#L36

I extracted the method (except the assert statement) and put it inside a method in my code. Then I used the set method of the transaction as below:

generateFirestoreId(){
        const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
        let autoId = '';
        for (let i = 0; i < 20; i++) {
            autoId += chars.charAt(Math.floor(Math.random() * chars.length));
        }
        //assert(autoId.length === 20, 'Invalid auto ID: ' + autoId);
        return autoId;
    }

then,

newDocRef = db.collection("PARENTCOLL").doc(PARENTDOCID).collection('SUBCOLL').doc(this.generateFirestoreId());
                        transaction.set(newDocRef,{
                            uid: userId,
                            name: name,
                            fsTimestamp: firebase.firestore.Timestamp.now(),
                        });

Since I am using the same algo for the id generation as the firestore itself I feel better.

Hope this helps/guides someone.

Cheers.

like image 35
honor Avatar answered Oct 19 '22 08:10

honor


Based on the answer from Doug Stevenson, this is how I got it worked with @angular/fire:

// Create a reference to a document and provide it a random id, e.g. by using uuidv4
const newDocRef = this.db.collection('coll').doc(uuidv4()).ref;

// In the transaction:
transaction.set(newDocRef, { ... });
like image 45
Stefan Avatar answered Oct 19 '22 08:10

Stefan