131

I know that in Realtime Database I could get the push ID before it was added like this:

 DatabaseReference databaseReference= FirebaseDatabase.getInstance().getReference();
 String challengeId=databaseReference.push().getKey();

and then I could add it using this ID.

Can I also get it in the Cloud Firestore?

Tal Barda
  • 4,067
  • 10
  • 28
  • 53

17 Answers17

219

This is covered in the documentation. See the last paragraph of the add a document section.

DocumentReference ref = db.collection("my_collection").doc();
String myId = ref.id;
Hugo Gresse
  • 17,195
  • 9
  • 77
  • 119
34m0
  • 5,755
  • 1
  • 30
  • 22
  • The same occurred to me... in firestore `.document()` does not give the impression of communicating with the database in the same was `push()` did. I believe the general view is that the likely hood of an id collision is so low that we do not have to be concerned with it. – 34m0 Oct 20 '17 at 09:05
  • @krv I don't see how .doc() would not work for you... 2 things you could verify are 1) you are using the correct method name for the sdk/library/language. .document() in java, .doc() in typescript/javascript. 2) you are calling .doc() on a collection reference and not a document reference. Bon courage! – 34m0 Jan 02 '18 at 13:33
  • 13
    got it working using angularFire2 by doing `this.db.collection('collections').ref.doc().id` – krv Jan 02 '18 at 13:34
  • Thank you @krv! That was exactly what I needed to do. How did you find it? I find the documentation of angularFire too short, and the API of Firebase differs a little from AngularFire. – eprats Jun 07 '18 at 07:14
  • @user3195091 I use VSCode that lets me check what methods a class has. – krv Jun 08 '18 at 05:08
  • getId() is deprecated now – Shin Jul 14 '19 at 21:31
  • 2
    I've updated this answer with to replace the old apis. – Hugo Gresse Jan 26 '20 at 13:15
  • ".doc()" also might not work for other languages, e. g. for Kotlin it would be ".document()". For some of them instead of ".id" we need to call ".getId" etc. – Liker777 Jun 28 '21 at 03:28
52
const db = firebase.firestore();
const ref = db.collection('your_collection_name').doc();
const id = ref.id;
Gastón Saillén
  • 12,319
  • 5
  • 67
  • 77
  • 27
    Please explain your answers, don't just dump out code – Sterling Archer Apr 05 '18 at 21:07
  • I'm using vue-fire and this one worked for me. Thanks. – Gene Parcellano Jul 21 '18 at 19:55
  • 7
    @SterlingArcher What's there to explain? Honest question. – Ruan Oct 21 '19 at 11:19
  • 3
    @Ruan a typical consideration that I was told a long time ago was “if it doesn’t need an explanation it would have been a question”. On that basis, we assume since were answering a question, an explanation as to *why* is usually required to help learn – Sterling Archer Oct 21 '19 at 16:20
  • @Ruan * How does this work * Does it only work for autogenerated keys * Does it work with transactions * Will I get a value before executing an update, or after * Is this answer up to date, or something changed. As a rule of thumb, please don't post snippets with no quoted source or explanation – Nacho Coloma Mar 20 '21 at 21:51
  • @NachoColoma You know I'm not a firebase expert myself, I just don't know if this works while using transactions. Why don't you try it and add your answer to this question and help a few peeps out. – Ruan Mar 23 '21 at 17:39
  • @Ruan The comment was about the form of this particular answer. For a better format, see the accepted answer that includes a link to the doc. – Nacho Coloma Mar 24 '21 at 06:06
26

You can do this in following manner (code is for AngularFire2 v5, which is similar to any other version of firebase SDK say web, node etc.)

const pushkey = this.afs.createId();
const project = {' pushKey': pushkey, ...data };
this.projectsRef.doc(pushkey).set(project);

projectsRef is firestore collection reference.

data is an object with key, value you want to upload to firestore.

afs is angularfirestore module injected in constructor.

This will generate a new document at Collection called projectsRef, with its id as pushKey and that document will have pushKey property same as id of document.

Remember, set will also delete any existing data

Actually .add() and .doc().set() are the same operations. But with .add() the id is auto generated and with .doc().set() you can provide custom id.

Jassi
  • 619
  • 7
  • 12
21

Firebase 9

doc(collection(this.afs, 'posts')).id;
Jonathan
  • 3,893
  • 5
  • 46
  • 77
19

The simplest and updated (2022) method that is the right answer to the main question:

"Is It Possible To Get The ID Before It Was Added?"

v8:

    // Generate "locally" a new document in a collection
    const document = yourFirestoreDb.collection('collectionName').doc();
    
    // Get the new document Id
    const documentUuid = document.id;
 
    // Sets the new document with its uuid as property
    const response = await document.set({
          uuid: documentUuid,
          ...
    });

v9:

    // Get the collection reference
    const collectionRef = collection(yourFirestoreDb,'collectionName');

    // Generate "locally" a new document for the given collection reference
    const docRef = doc(collectionRef); 

    // Get the new document Id
    const documentUuid = docRef.id;

    //  Sets the new document with its uuid as property
    await setDoc(docRef, { uuid: documentUuid, ... }) 
Frederiko Ribeiro
  • 1,844
  • 1
  • 18
  • 30
6

IDK if this helps, but I was wanting to get the id for the document from the Firestore database - that is, data that had already been entered into the console.

I wanted an easy way to access that ID on the fly, so I simply added it to the document object like so:

const querySnapshot = await db.collection("catalog").get();
      querySnapshot.forEach(category => {
        const categoryData = category.data();
        categoryData.id = category.id;

Now, I can access that id just like I would any other property.

IDK why the id isn't just part of .data() in the first place!

CodeFinity
  • 1,142
  • 2
  • 19
  • 19
  • Wondering if it's a good practice to do so. It would definitely make sense besides easing the client side usage of the data models – wiwi Feb 16 '19 at 22:47
  • Been a while since I looked at this, but I'm not aware of anything 'bad' from this approach. – CodeFinity Feb 18 '19 at 11:43
5

For node.js runtime

const documentRef = admin.firestore()
  .collection("pets")
  .doc()

await admin.firestore()
  .collection("pets")
  .doc(documentRef.id)
  .set({ id: documentRef.id })

This will create a new document with random ID, then set the document content to

{ id: new_document_id }

Hope that explains well how this works

tomrozb
  • 25,773
  • 31
  • 101
  • 122
3

Unfortunately, this will not work:

let db = Firestore.firestore()

let documentID = db.collection(“myCollection”).addDocument(data: ["field": 0]).documentID

db.collection(“myOtherCollection”).document(documentID).setData(["field": 0])

It doesn't work because the second statement executes before documentID is finished getting the document's ID. So, you have to wait for documentID to finish loading before you set the next document:

let db = Firestore.firestore()

var documentRef: DocumentReference?

documentRef = db.collection(“myCollection”).addDocument(data: ["field": 0]) { error in
    guard error == nil, let documentID = documentRef?.documentID else { return }

    db.collection(“myOtherCollection”).document(documentID).setData(["field": 0])
}

It's not the prettiest, but it is the only way to do what you are asking. This code is in Swift 5.

Ken Mueller
  • 3,659
  • 3
  • 21
  • 33
3

This is possible now (v9 2022 update) by generating Id locally:

import { doc, collection, getFirestore } from 'firebase/firestore'

const collectionObject = collection(getFirestore(),"collection_name") 
const docRef = doc(collectionObject)

console.log(docRef.id) // here you can get the document ID

Optional: After this you can create any document like this

setDoc(docRef, { ...docData })

Hope this helps someone. Cheers!

Junaid Nazir
  • 173
  • 1
  • 11
2

docs for generated id

We can see in the docs for doc() method. They will generate new ID and just create new id base on it. Then set new data using set() method.

try 
{
    var generatedID = currentRef.doc();
    var map = {'id': generatedID.id, 'name': 'New Data'};
    currentRef.doc(generatedID.id).set(map);
}
catch(e) 
{
    print(e);
}
Christopher Moore
  • 15,626
  • 10
  • 42
  • 52
2

For the new Firebase 9 (January 2022). In my case I am developing a comments section:

const commentsReference = await collection(database, 'yourCollection');
await addDoc(commentsReference, {
  ...comment,
  id: doc(commentsReference).id,
  date: firebase.firestore.Timestamp.fromDate(new Date())
});

Wrapping the collection reference (commentsReference) with the doc() provides an identifier (id)

Ferran Buireu
  • 28,630
  • 6
  • 39
  • 67
1

In dart you can use:

`var itemRef = Firestore.instance.collection("user")
 var doc = itemRef.document().documentID; // this is the id
 await itemRef.document(doc).setData(data).then((val){
   print("document Id ----------------------: $doc");
 });`
1

To get ID after save on Python:

doc_ref = db.collection('promotions').add(data)
return doc_ref[1].id
LinuxFelipe-COL
  • 381
  • 3
  • 7
1

You can use a helper method to generate a Firestore-ish ID and than call collection("name").doc(myID).set(dataObj) instead of collection("name").add(dataObj). Firebase will automatically create the document if the ID does not exist.

Helper method:

/**
 * generates a string, e.g. used as document ID
 * @param {number} len length of random string, default with firebase is 20
 * @return {string} a strich such as tyCiv5FpxRexG9JX4wjP
 */
function getDocumentId (len = 20): string {
  const list = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNPQRSTUVWXYZ123456789";
  let res = "";
  for (let i = 0; i < len; i++) {
    const rnd = Math.floor(Math.random() * list.length);
    res = res + list.charAt(rnd);
  }
  return res;
}

Usage: const myId = getDocumentId().

Boern
  • 7,233
  • 5
  • 55
  • 86
1

If you don't know what will be the collection at the time you need the id:

This is the code used by Firestore for generating ids:

const generateId = (): 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;
};

References:

Firestore: Are ids unique in the collection or globally?

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

cbdeveloper
  • 27,898
  • 37
  • 155
  • 336
0

This works for me. I update the document while in the same transaction. I create the document and immediately update the document with the document Id.

        let db = Firestore.firestore().collection(“cities”)

        var ref: DocumentReference? = nil
        ref = db.addDocument(data: [
            “Name” : “Los Angeles”,
            “State: : “CA”
        ]) { err in
            if let err = err {
                print("Error adding document: \(err)")
            } else {
                print("Document added with ID: \(ref!.documentID)")
                db.document(ref!.documentID).updateData([
                    “myDocumentId” : "\(ref!.documentID)"
                ]) { err in
                    if let err = err {
                        print("Error updating document: \(err)")
                    } else {
                        print("Document successfully updated")
                    }
                }
            }
        }

Would be nice to find a cleaner way to do it but until then this works for me.

GIJoeCodes
  • 1,680
  • 1
  • 25
  • 28
0

In Node

var id = db.collection("collection name").doc().id;
Snow
  • 411
  • 5
  • 8