Document

Document reference

the document reference identifies a document within a collection.

It embeds the information about the parent collection.

It is the combination of the parent collection reference (parent property) and its own id (id property). It also the result of an absolute path as a string (path property).

docRef.parent
docRef.id
docRed.path

use a document reference: CRUD

We provide the document reference for CRUD operations:

  • create a document (create-override) - setDoc(ref, data)

  • read the document - getDoc(ref)

  • update a document - updateDoc(ref, data)

  • delete a document - deleteDoc(ref)

compute a document reference

The path identifies the document uniquely. We provide it either as a single string or multiple strings.

If we provide a collectionRef, we may either provide a document ID, or skip the ID entirely. If we skip the ID, Firestore generate one for us.

In some cases, we may provide only the parent collection's reference.

  • compute a reference out of a path or ID.
const docRef = doc(collectionRef, id)
const docRef = doc(collectionRef) // ID is generated by firestore

const docRef = doc(db, "users", id) // collectionRef-less alternative
const docRef = doc(db, "users", "Nk....WQ")

const docRef = doc(db, "users/Nk....WQ") // path as single argument
const docRef = doc(db, "users/" + id)

const docRef = collectionRef.doc("John") // admin sdk
const docRef = collectionRef.doc("NkJz11WQ")

read single document

at ref, or at id

getDoc(docRef)
db.collection("messages").doc(id).get()

Document snapshot

the document snapshot is a wrapper that does not guarantee the document existence

A document snapshot does not guarantee the document existence. Firestore sends a document snapshot as a response, regardless if the requested document exists or not, that is, regardless if the document reference is empty or not.

As such, the promise does not reject and no error is thrown if no document exists for this document reference. Instead, we must check if the document snapshot is empty or not. If it is empty, the data() getter will return undefined.

As such, the snapshot is distinct from the document proper. The data is accessible through a method, data(options). The benefit of a method is the ability for us to provide a config object, rather than the data being provided as-is. Most of the time, we do not provide a config.

The snapshot embeds metadata along with the potential document. As such, it can be seen as a wrapper.

difference between the snapshot and the database document

The snapshot wraps some data that existed at a point in time, at the time of the fetch.

It is conceptually different from the document itself, who is mutable and may change at any time on the database. Meanwhile the snapshot remains unchanged, as a static/constant/immutable piece of data.

We cannot mutate the snapshot, but we may fetch a new snapshot, or we may subscribe to receive new snapshots in realtime on document mutation/deletion.

work with the snapshot and the underlying document.

check document existence

docSnapshot.exists()

get the underlying document if it exists.

const doc = docSnapshot.data() // undefined if document doesn't exist
// typescript infered type: DocumentData | undefined

guard against document inexistence (redundant but needed by typescript).

if (!doc) { .. }

then typecast, but only if collection didnt embed the type.

doc as FirestorePlanet

other props and methods

requested id, provided ref, resulting metadata.

docSnapshot.id
docSnapshot.ref
docSnapshot.metadata

get a single property directly through the document snapshot.

docSnapshot.get("phoneNumber")
earlymorning logo

© 2025 - All rights reserved

Document

Document reference

the document reference identifies a document within a collection.

It embeds the information about the parent collection.

It is the combination of the parent collection reference (parent property) and its own id (id property). It also the result of an absolute path as a string (path property).

docRef.parent
docRef.id
docRed.path

use a document reference: CRUD

We provide the document reference for CRUD operations:

  • create a document (create-override) - setDoc(ref, data)

  • read the document - getDoc(ref)

  • update a document - updateDoc(ref, data)

  • delete a document - deleteDoc(ref)

compute a document reference

The path identifies the document uniquely. We provide it either as a single string or multiple strings.

If we provide a collectionRef, we may either provide a document ID, or skip the ID entirely. If we skip the ID, Firestore generate one for us.

In some cases, we may provide only the parent collection's reference.

  • compute a reference out of a path or ID.
const docRef = doc(collectionRef, id)
const docRef = doc(collectionRef) // ID is generated by firestore

const docRef = doc(db, "users", id) // collectionRef-less alternative
const docRef = doc(db, "users", "Nk....WQ")

const docRef = doc(db, "users/Nk....WQ") // path as single argument
const docRef = doc(db, "users/" + id)

const docRef = collectionRef.doc("John") // admin sdk
const docRef = collectionRef.doc("NkJz11WQ")

read single document

at ref, or at id

getDoc(docRef)
db.collection("messages").doc(id).get()

Document snapshot

the document snapshot is a wrapper that does not guarantee the document existence

A document snapshot does not guarantee the document existence. Firestore sends a document snapshot as a response, regardless if the requested document exists or not, that is, regardless if the document reference is empty or not.

As such, the promise does not reject and no error is thrown if no document exists for this document reference. Instead, we must check if the document snapshot is empty or not. If it is empty, the data() getter will return undefined.

As such, the snapshot is distinct from the document proper. The data is accessible through a method, data(options). The benefit of a method is the ability for us to provide a config object, rather than the data being provided as-is. Most of the time, we do not provide a config.

The snapshot embeds metadata along with the potential document. As such, it can be seen as a wrapper.

difference between the snapshot and the database document

The snapshot wraps some data that existed at a point in time, at the time of the fetch.

It is conceptually different from the document itself, who is mutable and may change at any time on the database. Meanwhile the snapshot remains unchanged, as a static/constant/immutable piece of data.

We cannot mutate the snapshot, but we may fetch a new snapshot, or we may subscribe to receive new snapshots in realtime on document mutation/deletion.

work with the snapshot and the underlying document.

check document existence

docSnapshot.exists()

get the underlying document if it exists.

const doc = docSnapshot.data() // undefined if document doesn't exist
// typescript infered type: DocumentData | undefined

guard against document inexistence (redundant but needed by typescript).

if (!doc) { .. }

then typecast, but only if collection didnt embed the type.

doc as FirestorePlanet

other props and methods

requested id, provided ref, resulting metadata.

docSnapshot.id
docSnapshot.ref
docSnapshot.metadata

get a single property directly through the document snapshot.

docSnapshot.get("phoneNumber")