Firestore - How to get document id after adding a document to a collection

FirebaseGoogle Cloud-Firestore

Firebase Problem Overview


Is there a way to acquire the document id that was generated after adding a document to a collection?

If I add a document to a collection that represents a "post" in a social media app, I want to get that document id and use it as a field in another document in a different collection.

If I can't get the document Id that was generated after adding a document, should I just compute a random string and supply the id when creating the document instead? That way I can use that same string as the field in my other document?

Quick structure example:

POST (collection)
    Document Id - randomly generated by firebase or by me
USER (collection)
    Document Id - randomly generated by firebase
       userPost: String (this will be the document id 
                         in the post collection that I'm trying to get)

Firebase Solutions


Solution 1 - Firebase

Yes it is possible. When you call the .add method on a collection, a DocumentReference object is returned. DocumentReference has the id field, so you can get the id after the document was created.

// Add a new document with a generated id. db.collection("cities").add({ name: "Tokyo", country: "Japan" }) .then(function(docRef) { console.log("Document written with ID: ", docRef.id); }) .catch(function(error) { console.error("Error adding document: ", error); }); This example is in JavaScript. Visit the documentation for other languages.

Solution 2 - Firebase

If using promises, I'd recommend using fat arrow function as it opens up the possibility for using this.foo even in the .then function

    db.collection("cities").add({
        name: "Tokyo",
        country: "Japan"
    })
    .then(docRef => {
        console.log("Document written with ID: ", docRef.id);
        console.log("You can now also access this. as expected: ", this.foo)
    })
    .catch(error => console.error("Error adding document: ", error))

Using function(docRef) means you cannot access this.foo, and error will be thrown

    .then(function(docRef) {
        console.log("Document written with ID: ", docRef.id);
        console.log("You can now NOT access this. as expected: ", this.foo)
    })

While fat arrow functions will allow you to access this.foo as expected

    .then(docRef => {
        console.log("Document written with ID: ", docRef.id);
        console.log("You can now also access this. as expected: ", this.foo)
    })

Edit/addition 2020:

A more popular way these days may be to use async/await instead. Notice that you have to add async in front of the function declaration:

    async function addCity(newCity) {
      const newCityAdded = await db.collection("cities").add(newCity)
      console.log("the new city:", newCityAdded)
      console.log("it's id:", newCityAdded.id)
    }

And if you only want the id it can be grabbed using descructuring. Destructuring allows you to grab any key/value-pair in the response:

    async function addCity(newCity) {
      const { id } = await db.collection("cities").add(newCity)
      console.log("the new city's id:", id)
    }

It's also possible to use destructuring to grab the value and rename to whatever you want:

    async function addCity(newCity) {
      const { id: newCityId } = await db.collection("cities").add(newCity)
      console.log("the new city's id:", newCityId)
    }

Solution 3 - Firebase

If you want to use async/await instead of .then(), you can write it like this:

const post = async (doc) => {
    const doc_ref = await db.collection(my_collection).add(doc)
    return doc_ref.id
}

If you want to catch any errors in this function, include .catch():

    const doc_ref = await db.collection(my_collection).add(doc).catch(err => { ... })

or you can have the calling function catch the error.

Solution 4 - Firebase

For Android, Java, you're suppose to get the Document ID before you set() or add() something to Firestore. Like so:

    //Fields: 
    CollectionReference toolsCollectionRef = FirebaseFirestore.getInstance().collection(toolsCollection);
    CustomPOJO_Model toolToPost; 
    
    //In Methods: 
    String newDocID= toolsCollectionRef.document().getId();   //Get Doc ID first. 
    toolToPost.setToolID(newDocID);
    
    //Now use the doc ID:
    toolsCollectionRef.document(newDocID).set(toolToPost.getConvertedTool_KeyValuePair ()).addOnCompleteListener(new OnCompleteListener<Void>() {
        @Override
        public void onComplete(@NonNull Task<Void> task) {
        }
    });
    
    //Re-use same ID in another post: 
    usersCollectionRef.document(mAuth.getUid()).collection(usersToolsCollection).document(toolToPost.getToolID()).set(toolToPost.getConvertedTool_KeyValuePair()); 

Solution 5 - Firebase

As others mentioned also, we can get the document reference once it added. After we get the document reference on the behalf of id, we can update the same

Service.ts file

async funName(data: Data){
      let docRef = this.firestore.collection('table-name').add(data);
      console.log(docRef)
      try {
        const docAdded = await docRef;
        console.log(docAdded.id);
        this.firestore.doc('table-name/' + docAdded.id).update({ id: docAdded.id });
        return docRef;
      }
      catch (err) {
        return err;
      }
    }

component.ts file

async addData(){
    try{
      let res =  await this.dataServ.funName(this.form.value);
      this.snackbar.open('success', 'Success');
    }catch(ex){
      this.disabled = false;
      this.snackbar.open('err', 'Error')
      console.log(ex, 'exception');
    }
  }

Solution 6 - Firebase

for FB Firestore version 9 (JS/Web) use the following syntax:

import { addDoc, doc, Timestamp, updateDoc } from "firebase/firestore";

    //add document to 'posts' collection with auto id
        const newItem = await addDoc(collection(db, 'posts'), {
                  caption: post.value.caption || "No caption provided",
                  location: post.value.location || "No location provided",
                  imageUrl: imageUrl.value,
                  createdAt: Timestamp.now(), 
            });
                
    //get new document id an update it to the file as id field.
    const fileID = newItem.id
                console.log('added file:', fileID);
                const updateDocId = doc(db, "posts", fileID) ;
                await updateDoc(updateDocId, {
                  id: fileID
              })

Solution 7 - Firebase

Here's what I do, as mentioned in your question. Not sure if it is best practice, but it works for easy access.

When creating the document in the first place

firebase.firestore().collection("cities").doc().set({ name: Tokyo,
country: Japan })

you can set the id of the doc and put that exact id in it as a property:

firebase.firestore().collection("cities").doc('id-generated-from-somewhere')
.set({ id: 'id-generated-from-somewhere', name: Tokyo, country: Japan })

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionBrejuroView Question on Stackoverflow
Solution 1 - FirebaseDaniel KonovalenkoView Answer on Stackoverflow
Solution 2 - FirebaseChristofferView Answer on Stackoverflow
Solution 3 - FirebaseBrent WashburneView Answer on Stackoverflow
Solution 4 - FirebaseGeneView Answer on Stackoverflow
Solution 5 - FirebaseVIKAS KOHLIView Answer on Stackoverflow
Solution 6 - FirebaseMichael JCView Answer on Stackoverflow
Solution 7 - FirebaseStephen HartfieldView Answer on Stackoverflow