Collection

Collection Reference

uses

We provide the collection reference to:

  • fetch all documents - getDocs(colRef)

  • build a query targeting the collection - query(colRef, filters..)

  • build an empty document reference within the collection - doc(colRef)

  • add a document to the collection, by submitting data and delegating the id creation to the SDK - addDoc(colRef, data). (it returns the reference)

We may also use it in combination with a document's ID to uniquely identify this document, such as in getDoc(colRef, id)

A documentRef already encapsulates the collection reference. As such, we don't need to provide both.

build a collection reference

The path to the collection identifies it uniquely. If the collection lives at the top, aka is not a sub-collection, the path is the same as the collection name, such as "users". Otherwise it's made of several components.

We indicate the collection's path, either as:

  • a single string, with no starting slash for the root collection

  • a sequence of string arguments with no slash.

const collectionRef = collection(db, "users")
const collectionRef = collection(db, `users/${uid}/custom_list`)
const collectionRef = collection(db, "users", uid, "custom_list")
// firebase-admin/firestore
const collectionRef = db.collection("users")
const collectionRef = db.collection(`users/${uid}/custom_list`)

Typescript: indicate the document's type at the collection level.

The SDK cannot infer the document type for a given collection. As such, we provide it at the collection reference level.

We may have a client specific type, one that results from a client-side transformation, that we do with a converter. In that case, we provide the client-side type first. Otherwise, we provide the same type twice.

const playersColRef = collectionRef as CollectionReference<Player, Player>
const playersColRef = collectionRef as CollectionReference<Player, FirestorePlayer>
const playersColRef = collectionRef.withConverter(myConverter)

Firestore Converter

declare transform between firestore shape and client shape.

We may want to have a shape on the client that is distinct from the one in the database. For example:

  • a property is a Timestamp in the database, but we want a Date on the client.
  • We want to add client only properties, such as helper properties.

In this case, we want Firebase to transform the document when

  • receiving it from Firestore (fromFirestore())
  • sending it to Firestore (toFirestore())

We define a converter, made of two functions.

fromFirestore takes a query document snapshot.:

fromFirestore(snapshot: QueryDocumentSnapshot<FirestoreWorkout>): Workout{
		// transform to client shape
		const firestoreWorkout = snapshot.data()
		const workout = { ...firestoreItem, date: firestoreItem.date.toDate()}
     return workout
    }

toFirestore takes the local object.

toFirestore(workout: Workout) {
		// prepare the object for firestore
        	return { ...workout, date: Timestamp.fromDate(workout.date)}
    }

and put them in a data converter of type FirestoreDataConverter, which dictates both types, provided as type parameters following the shape of: FirestoreDataConverter<AppModel, DbModel>

const myConverter: FirestoreDataConverter<Workout, FirestoreWorkout> = {
    toFirestore() {},
    fromFirestore() {},
}

attach the converter to the collectionRef

We attach the converter with withConverter()

const collectionRef = collection(db, "users").withConverter(myConverter)

cloud functions may not use a converter

the Admin SDK does not provide withConverter()

earlymorning logo

© 2025 - All rights reserved

Collection

Collection Reference

uses

We provide the collection reference to:

  • fetch all documents - getDocs(colRef)

  • build a query targeting the collection - query(colRef, filters..)

  • build an empty document reference within the collection - doc(colRef)

  • add a document to the collection, by submitting data and delegating the id creation to the SDK - addDoc(colRef, data). (it returns the reference)

We may also use it in combination with a document's ID to uniquely identify this document, such as in getDoc(colRef, id)

A documentRef already encapsulates the collection reference. As such, we don't need to provide both.

build a collection reference

The path to the collection identifies it uniquely. If the collection lives at the top, aka is not a sub-collection, the path is the same as the collection name, such as "users". Otherwise it's made of several components.

We indicate the collection's path, either as:

  • a single string, with no starting slash for the root collection

  • a sequence of string arguments with no slash.

const collectionRef = collection(db, "users")
const collectionRef = collection(db, `users/${uid}/custom_list`)
const collectionRef = collection(db, "users", uid, "custom_list")
// firebase-admin/firestore
const collectionRef = db.collection("users")
const collectionRef = db.collection(`users/${uid}/custom_list`)

Typescript: indicate the document's type at the collection level.

The SDK cannot infer the document type for a given collection. As such, we provide it at the collection reference level.

We may have a client specific type, one that results from a client-side transformation, that we do with a converter. In that case, we provide the client-side type first. Otherwise, we provide the same type twice.

const playersColRef = collectionRef as CollectionReference<Player, Player>
const playersColRef = collectionRef as CollectionReference<Player, FirestorePlayer>
const playersColRef = collectionRef.withConverter(myConverter)

Firestore Converter

declare transform between firestore shape and client shape.

We may want to have a shape on the client that is distinct from the one in the database. For example:

  • a property is a Timestamp in the database, but we want a Date on the client.
  • We want to add client only properties, such as helper properties.

In this case, we want Firebase to transform the document when

  • receiving it from Firestore (fromFirestore())
  • sending it to Firestore (toFirestore())

We define a converter, made of two functions.

fromFirestore takes a query document snapshot.:

fromFirestore(snapshot: QueryDocumentSnapshot<FirestoreWorkout>): Workout{
		// transform to client shape
		const firestoreWorkout = snapshot.data()
		const workout = { ...firestoreItem, date: firestoreItem.date.toDate()}
     return workout
    }

toFirestore takes the local object.

toFirestore(workout: Workout) {
		// prepare the object for firestore
        	return { ...workout, date: Timestamp.fromDate(workout.date)}
    }

and put them in a data converter of type FirestoreDataConverter, which dictates both types, provided as type parameters following the shape of: FirestoreDataConverter<AppModel, DbModel>

const myConverter: FirestoreDataConverter<Workout, FirestoreWorkout> = {
    toFirestore() {},
    fromFirestore() {},
}

attach the converter to the collectionRef

We attach the converter with withConverter()

const collectionRef = collection(db, "users").withConverter(myConverter)

cloud functions may not use a converter

the Admin SDK does not provide withConverter()