Query
overview
A query matches documents based on a set of criteria, instead of pre-defined document references.
the result of a query: a query snapshot
The query snapshot hosts the list of document snapshots (docs). The list is empty when no match occurred.
The document snapshots are of type QueryDocumentSnapshot (not DocumentSnapshot) but they have the same API surface. They are guaranteed to have an underlying document at snapshot.data() (this is the difference).
querySnaptshot.docs // list of document snapshots
querySnaptshot.empty
const cats = querySnapshot.docs.map((snap) => snap.data())
a collection reference is a query
A collection ref is technically a query and is used to target all documents in a read (get):
getDocs(q)
getDocs(colRef)
q.get()
colRef.get()
build a query
We add value-based filters, set the order and limit the count:
const q = query(colRef, where(..), where(..), orderBy(..), limit(..))
const q = collection(..).where(..).orderBy(..).limit(..)
where filter: look for documents with a given value
We filter documents based on a value we want to find in a property. We request an exact value or one within a range. Depending on the data, we expect a single match at most or several.
Note: documents that do not possess the property are filtered out.
For example, we look for the document whose id is of value user.id.
where(propertyName, operator, value)
where("id", "==", user.id)
set the requirement for the value: exact match, being different, being smaller or larger, exact match with at least one value, or different from all values.
==
!=
<
<=
>
>=
"in" // the property is equal to either A, B or C
"not-in" // the property is different from A, B and C.
We can also ask the value to be included or excluded from the array if the property is an array.
"array-contains" // the array contains this value
"array-contains-any" // the array contains A, B or C..
order documents based on one field
We order documents based on the value of a given field. By default, it sorts documents so that the value is ascending. It's best to set the order explicitly rather than relying on the default ascending order.
orderBy(propertyName, orderDirection)
orderBy("postCount", "asc")
orderBy("postCount", "desc")
We can start from a given value, e.g. documents that have at least 10 posts (or more than 10 posts).
startAt(10)
startAfter(10)
pagination: cap the read, read the next page
Get at most n documents:
limit(20)
To get the next page, we provide a cutoff document (snapshot), stored from the current batch: we receive document snapshots starting beyond it:
query(colRef, startAfter(docSnapshot), limit(20))
While we can include the cutoff document in the next batch, it is mostly for other patterns:
startAt(docSnapshot)
run the query (get)
const qs = getDocs(query)
const qs = query.get()
real-time listener
Set up a real-time listener on the query: we receive a query snapshot:
const unsub = onSnapshot(query, (qs) => {
const documents = qs.docs.map((docSnapshot) => docSnapshot.data())
setMessages(documents)
})