Firestore - How to get document id after adding a document to a collection
FirebaseGoogle Cloud-FirestoreFirebase 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 })