1

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.

Celso Marigo Jr
  • 656
  • 1
  • 14
  • 35
  • 1
    Can you please show your database structure? My assumption is that you aren't querying the correct data hence not getting the _users_ under a certain _producer_. If your data looks something like this: producers -> producer -> users -> user {id and producerField}, you may need to query the _producers_ collection to retrieve the correct _producer_ document, which will give you access to its list of _users_. – sllopis Jul 17 '20 at 15:12
  • @sllopis i just added my data structure, I putted two records, one with UID starting with '06' is the producer, and the other users are related to him, in the field `produtor`. – Celso Marigo Jr Jul 17 '20 at 17:04

2 Answers2

0

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()
wlf
  • 3,086
  • 1
  • 19
  • 29
  • Actually this `OR` condition was because the user logged could be the producer itself, then the field `producer`wouldn´t exists is this document, but, I´d chang it, and putted the field there to test. But it keeps returning only one record on query, the logged user. – Celso Marigo Jr Jul 17 '20 at 13:32
0

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.

Nibrass H
  • 2,403
  • 1
  • 8
  • 14