Angular Fire fetching related data from same collection

265 views Asked by At

I´m facing a strange behavior with a query on my firestore project. One user of the project is like the owner of the system, we call him the producer. And the other users, can belong to one producer, so I have a collection of users, where I have a field called producer, with the producer ID, like below.

{user: {id: '...', producer: '...', ...}

enter image description here *Translate producer to produtor.

I have a functionality called a transfer, where I can transfer cash from one user account to another, but only within the users of the same producer. So I need to fetch all the users where the producer is the same as the logged user, on this collection, here is my function:

constructor(
  private afAuth: AngularFireAuth,
  private afs: AngularFirestore
) { }

fetchUsers() {
  return this.afAuth.authState.pipe(
    switchMap( user => { // Here I have the logged user
      return this.afs.doc(`users/${user.uid}`).valueChanges() // Here I need his details on users collection
    }),
    first(),
    switchMap( (user: any) => {
      return this.afs.collection('users',
        ref => ref.where('producer', '==', user.producer) // Now I want the other users from same producer
      ).valueChanges()
    })
  )
}

But it does not work, the only user on the result is the user calling the function. Is it a limitation of the Angular Fire or maybe I´m doing it in the wrong way?

I think it´s maybe a bug, because I could workaround this using get on document and then on collection:

return this.afAuth.authState.pipe(
            switchMap( user => {
                return this.afs.doc(`users/${user.uid}`).get()
            }),
            first(),
            map( usuario => {
                return usuario.data()
            }),
            switchMap( (usuario: any) => {
                return this.afs.collection('users', ref => ref.where('produtor', '==', usuario.produtor)).get()
            }),
            first(),
            map( data => {
                let users = []
                data.docs.map( doc => {
                    users.push(doc.data())
                })
                return users
            })
       )

This way, it returns all the users where the producer, produtor, is the same of logged in user. I´ll appreciate if someone could explain me why.

2

There are 2 answers

1
wlf On

Looks like your OR query logic is incorrect.

return this.afs.collection('users',
        ref => ref.where('producer', 'in', [user.producer, user.uid]) 
).valueChanges()

https://firebase.google.com/docs/firestore/query-data/queries

In fact it appears you do not need an OR condition at all. Why would user.producer be set to two different types?

ie: if user.producer is always set to a producer ID, then you can have just:

return this.afs.collection('users',
            ref => ref.where('producer', '==', user.uid) 
    ).valueChanges()
0
Nibrass H On

When you call .valueChanges() in Angular Fire, it returns an observable.

Observables open up a continuous channel of communication in which multiple values of data can be emitted over time.

So we need to get a value from an Observable and for that we need to subscribe to it. You could call the document with for valueChanges and attach a pipe(take(1)) as following, but get() is pretty handy.

   this.afs.doc(`users/${user.uid}`).valueChanges()
   .pipe(take(1))
   .subscribe(v => {
       console.log(v);
    });

Please let me know if you need any further clarification.