-
Notifications
You must be signed in to change notification settings - Fork 150
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[FR] Ability to get all descendants #2285
Comments
Would you be willing to take a Pull Request for this? If so, I could try to create one. |
Thanks for poking around!! This is great to see. The reason we do not have this as an official API is that this would not work with In the meantime, please continue to use your walkaround. I will post something here when we do have it as a public API. |
Ah, I see. That makes the public API design a bit more tricky. Exposing this as something similar to But exposing as a full blown For our own workaround we'll just live with a For others interesting in a similar workaround in your own codebase. Be aware how When query'ing with When setting both This had us confused for a while and we think it is an easier mental model when initiating this type of query from a Having that utility method means we have to start from a So, for the eventual public API design I feel it would be nice to have a A similar |
So that gives us a way to query for all
That is, find all docs that live under a certain parent doc (or the root database I guess), with or without a certain collection-name as direct parent. It does not give us a way to find all docs that live under a certain collection ( It turns out there is a way to do that, which you can find in the nodejs-firestore/dev/src/recursive-delete.ts Lines 258 to 268 in f58fe79
You can look at the complete method for more inspiration if you need anything like that. |
We have created a utility function that works in most situations. Perhaps this is helpful to other people looking into this: import { Query } from '@google-cloud/firestore';
import { QueryOptions } from '@google-cloud/firestore/build/src/reference/query-options';
import assert from 'assert';
/**
* Builds a `Query` that queries all recursively descendant documents from a given document. When `collection` is given it only returns
* documents where its immediate parent collection has this name. Please note that this parent collection does not have to be a direct child
* of the given `DocumentReference` since the query is recursive.
*
* Descendant documents will be found even if the given `DocumentReference` itself, or any intermediate documents, do not actually exist.
*
* The returned query does not support live queries and `onSnapshot` will throw a runtime error
*
* When the query was constructed without a `collection` argument, you cannot use `withConverter` on it as that will re-introduce an (internal)
* predicate on the `collectionId` with a non existing collection.
*/
export function allDescendants(parent: FirebaseFirestore.DocumentReference, collection?: string) {
// determine if this will be a "kindless" query meaning without restriction on the name of the direct parent (collection) of the found
// documents.
const kindless = collection === undefined;
// build a query from the document reference and optionally restrict the name of the collection owning the found document(s)
const query = parent.collection(kindless ? 'unused' : collection);
assert('_queryOptions' in query, 'Firestore query always has private _queryOptions');
// cast Query as its constructor is `protected` and we need a public constructor for Typescript to not complain.
const PublicQuery = Query as unknown as {
new (
firestore: FirebaseFirestore.Firestore,
options: QueryOptions<unknown, FirebaseFirestore.DocumentData>,
): FirebaseFirestore.Query;
};
// construct a new Query instance with a new QueryOptions instance similar to what Query does internally in the other query building
// methods.
return new PublicQuery(
query.firestore,
(query._queryOptions as QueryOptions<unknown, FirebaseFirestore.DocumentData>).with({
allDescendants: true,
kindless,
}),
);
} And have a look at the unit tests for the (Rust based) Firestore Emulator to see how such a |
We would love to have the ability to query all descendants of a document (or collection) even when the intermediate documents do not exist.
For example, let's say
/my-collection/my-doc/my-sub-collection/my-sub-doc
(and many siblings) exists in Firestore, but/my-collection/my-doc
does not exist. It's then not possible to query those documents from the sub-collection. Most of the pieces seem to exist inQueryOptions.forKindlessAllDescendants
that is used fromRecursiveDelete.getAllDescendants
but those are all private.We currently achieve this by getting the
FirestoreClient
from@google-cloud/firestore/types/v1
by poking in some internal variables of the public Firestore client and then invoking therunQuery
method on that client:But this is a hassle and we get raw protobuf responses that we need to serialize and all the other good stuff that the public Firestore client normally does.
Another alternative is to manipulate
allDescendants
directly in theQueryOptions
(which also works):It would be wonderful if a
.allDescendants()
method could be added toCollectionReference
that setsallDescendants
inQueryOptions
totrue
. The rest of the handling seems to be there.The text was updated successfully, but these errors were encountered: