eye4eneye
eye4eneye

Reputation: 61

Running a collection group query to see if a field in my firebase subcollection is true or false

I'm creating a sign in method that is trying to check if my current user has agreed to my terms of agreement after verifying their email address. My function is as follows:

SignIn(email, password) {
    return this.afAuth.auth.signInWithEmailAndPassword(email, password)
        .then(cred => {
            this.ngZone.run(() => {
                // Gets current signed in user.
                this.afAuth.authState.subscribe(user => {
                    // Queries Details subcollection.
            this.db.collection('users').doc(user.uid).collection('Details')
                        .get().toPromise().then(
                            doc => {
                                if (user.termsOfAgreement == false) {
                                    this.router.navigate(['terms']);
                                } else {
                                    this.router.navigate(['dashboard']);
                                }
                            })
                })
            });
        }).catch((error) => {
            window.alert(error.message)
        })
}

I know that I'm getting the firebase user object and that it doesn't contain my specific sub collection field names (i.e. user.termsOfAgreement). But how would I access those? I'm trying to check if my termsOfAgreement field is true or false.

My Firestore User Collection state on sign up

User (Collection)
- lastLogin: timestamp
- name: string
- userId: string

Details (subcollection)
- termsOfAgreement: false 

Upvotes: 0

Views: 87

Answers (1)

Frank van Puffelen
Frank van Puffelen

Reputation: 599716

First note that this.db.collection('users').doc(user.uid).collection('Details') is not a collection group query, but a read operation on a single collection.

It sounds like you want to check if the Details collection under the user document contains a document with termsOfAgreement equal to true. You can most easily check that with:

firebase.firestore()
        .collection('users').doc(user.uid)
        .collection('Details').where('termsOfAgreement', '==', true).limit(1)
        .get().then((querySnapshot) => {
            if (querySnapshot.empty == false) {
                this.router.navigate(['terms']);
            } else {
                this.router.navigate(['dashboard']);
            }
        })

The above code is using the regular JavaScript SDK, as there is no need to use AngularFire for this operation. But aside from that, it'd work the same in either: you fire a query against the collection and then check if there's any results.

In addition to fixing your code, this also optimizes it in two ways:

  1. The query is sent to the server, so that you're only transferring data that matches the condition.
  2. At most one document is transferred, since you only care whether any result exists.

I'm not sure why you're storing termsOfAgreement in the subcollection though.

If you're checking for the existence of any subdocument where the termsOfAgreement is true, you might want to consider adding a termsOfAgreement field to the user document itself, so that you don't need to perform a query across the subcollection.

You'd set this userDoc.termsOfAgreement to true once the user accepts any terms in the subcollection, and then won't have to query the subcollection anymore (simplifying the reading code and reducing the number of read operations).

Upvotes: 1

Related Questions