Skip to main content
SubCollectionAccessor provides a concise, parent-scoped interface for querying and mutating subcollection documents. You obtain an instance by calling parent_instance.subcollection(ChildModel) rather than constructing it directly. Every operation the accessor exposes is equivalent to calling the corresponding class method on the child model with parent=parent_instance, but the Beanie-inspired fluent style makes subcollection code easier to read.

Obtaining an accessor

Call subcollection() on any hydrated BaseFirestoreModel instance and pass the child model class:
subcollection() immediately validates that Post.Settings.parent equals type(user) (i.e. User). A ValueError is raised if the child class does not declare the correct parent type — this catches misconfigured models at the earliest possible moment.
The child model class must declare Settings.parent = User (or whatever the parent type is). Passing a top-level collection model raises ValueError: Post does not declare Settings.parent = User.

Methods

add

Create a new document in the subcollection. Delegates to doc.save(parent=self._parent, **kwargs).
BaseFirestoreModel
required
An unsaved model instance to persist. If doc.id is None, Firestore auto-generates a document ID.
Any
Additional keyword arguments forwarded to save(). Supported keys include exclude_none (default True), by_alias (default True), and exclude_unset (default True).
Returns the saved instance with id populated.

get

Retrieve a single subcollection document by its document ID.
str
required
The Firestore document ID to look up within the subcollection.
Returns the hydrated child model instance, or None if no document with that ID exists in this parent’s subcollection.

find

Stream all documents in the subcollection that match the given filters. Returns an AsyncGenerator — iterate with async for.
List[Tuple[FieldType, FirestoreOperators, Any]] | None
Filter tuples to apply. Build them with FirestoreField expressions (Post.published == True) or raw (field, operator, value) tuples. Defaults to None (returns all documents).
Any
Additional keyword arguments forwarded to BaseFirestoreModel.find(). Supported keys include projection, order_by, limit, and offset.

find_one

Return the first document in the subcollection that matches the given filters, or None if no match is found.
List[Tuple[FieldType, FirestoreOperators, Any]] | None
Filter tuples. Passing None or [] returns the first document in the subcollection.
Any
Additional keyword arguments forwarded to BaseFirestoreModel.find_one(). Supported keys include projection and order_by.

count

Return the number of documents in the subcollection that match the given filters.
List[Tuple[FieldType, FirestoreOperators, Any]] | None
Filter tuples. Passing None counts all documents in the subcollection.

exists

Return True if a document with the given ID exists in this parent’s subcollection.
str
required
The Firestore document ID to check within the subcollection.

delete

Delete a document from the subcollection. The document instance must have a non-None id.
BaseFirestoreModel
required
A hydrated child model instance to delete. Delegates to doc.delete() — the cascade parameter from BaseFirestoreModel.delete is not exposed here; call doc.delete(cascade=True) directly if you need recursive deletion.

Accessor vs. direct class methods

Both styles are fully equivalent. The accessor is a syntactic convenience — choose whichever reads more clearly in your codebase.
The accessor style is especially readable when you make multiple calls against the same parent–child pair in one function, because you only reference the parent once when constructing the accessor.

Full subcollection example