Firestore Getting documents id from collection

AngularFirebaseGoogle Cloud-FirestoreNosqlAngularfire2

Angular Problem Overview


I'm trying to retrieve my documents with id but can't figure it out.
Currently I retrieve my documents like this :

const racesCollection: AngularFirestoreCollection<Races> = this.afs.collection('races');
return racesCollection.valueChanges();

I do get my documents list perfectly, however there is no doc id with them.

How can I retrieve it for each document ?

Angular Solutions


Solution 1 - Angular

For angular 8 and Firebase 6 you can use the option id field

      getAllDocs() {
           const ref = this.db.collection('items');
           return ref.valueChanges({idField: 'customIdName'});
      }

this adds the Id of the document on the object with a specified key (customIdName)

Solution 2 - Angular

To obtain the id of the documents in a collection, you must use snapshotChanges()

    this.shirtCollection = afs.collection<Shirt>('shirts');
    // .snapshotChanges() returns a DocumentChangeAction[], which contains
    // a lot of information about "what happened" with each change. If you want to
    // get the data and the id use the map operator.
    this.shirts = this.shirtCollection.snapshotChanges().map(actions => {
      return actions.map(a => {
        const data = a.payload.doc.data() as Shirt;
        const id = a.payload.doc.id;
        return { id, ...data };
      });
    });

Documentation https://github.com/angular/angularfire2/blob/7eb3e51022c7381dfc94ffb9e12555065f060639/docs/firestore/collections.md#example

Solution 3 - Angular

I've finally found the solution. Victor was close with the doc data.

const racesCollection: AngularFirestoreCollection<Race>;
return racesCollection.snapshotChanges().map(actions => {       
  return actions.map(a => {
    const data = a.payload.doc.data() as Race;
    data.id = a.payload.doc.id;
    return data;
  });
});

ValueChanges() doesn't include metadata, therefor we must use SnapshotChanges() when we require the document id and then map it properly as stated here https://github.com/angular/angularfire2/blob/master/docs/firestore/collections.md

Solution 4 - Angular

For angular6+

    this.shirtCollection = afs.collection<Shirt>('shirts');
    this.shirts = this.shirtCollection.snapshotChanges().pipe(
        map(actions => {
        return actions.map(a => {
            const data = a.payload.doc.data() as Shirt;
            const id = a.payload.doc.id;
            return { id, ...data };
        });
        })
    );

Solution 5 - Angular

doc.id gets the UID.

Combine with the rest of the data for one object like so:

Object.assign({ uid: doc.id }, doc.data())

Solution 6 - Angular

Since you are using angularFire, it doesn't make any sense if you are going back to default firebase methods for your implementation. AngularFire itself has the proper mechanisms implemented. Just have to use it.

valueChanges() method of angularFire provides an overload for getting the ID of each document of the collection by simply adding a object as a parameter to the method.

valueChanges({ idField: 'id' })

Here 'idField' must be same as it is. 'id' can be anything that you want your document IDs to be called.

Then the each document object on the returned array will look like this.

{
  field1 = <field1 value>,
  field2 = <field2 value>,
  ..
  id = 'whatEverTheDocumentIdWas'
}

Then you can easily get the document ID by referencing to the field that you named.

AngularFire 5.2.0

Solution 7 - Angular

Can get ID before add documents in database:

var idBefore =  this.afs.createId();
console.log(idBefore);

Solution 8 - Angular

For document references, not collections, you need:

// when you know the 'id'

this.afs.doc(`items/${id}`)
  .snapshotChanges().pipe(
    map((doc: any) => {
      const data = doc.payload.data();
      const id = doc.payload.id;
      return { id, ...data };
    });

as .valueChanges({ idField: 'id'}); will not work here. I assume it was not implemented since generally you search for a document by the id...

Solution 9 - Angular

I have tried this

return this.db.collection('items').snapshotChanges().pipe(
          map(actions => {       
            return actions.map(a => {
              const data = a.payload.doc.data() as Item;
              data.id = a.payload.doc.id;
              data.$key = a.payload.doc.id;
              return data;
            });
          })
        );

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
QuestionDominikGView Question on Stackoverflow
Solution 1 - AngularIvan TarskichView Answer on Stackoverflow
Solution 2 - AngularLuis Ruiz FigueroaView Answer on Stackoverflow
Solution 3 - AngularDominikGView Answer on Stackoverflow
Solution 4 - AngularphiconView Answer on Stackoverflow
Solution 5 - AngularcorysimmonsView Answer on Stackoverflow
Solution 6 - AngularHasintha AbeykoonView Answer on Stackoverflow
Solution 7 - AngularDiego VenâncioView Answer on Stackoverflow
Solution 8 - AngularJonathanView Answer on Stackoverflow
Solution 9 - AngularTrilok SinghView Answer on Stackoverflow