0

I am just getting started with Firebase and am trying to determine how to best structure my Firestore database.

What I want is to find all documents from an 'events' collection where 'participants' (which is an array field on each event document which contains objects with keys 'displayName' and 'uid') contains at least one matching uid. The list of uids I am comparing against will be the users' friends.

So in more semantic terms, I want to find all events where at least one of the participants of that event is a 'friend', using the uid of the event participants and of the users friends.

Hope I haven't lost you. Maybe this screenshot will help.

Here is how I've designed the 'events' collection right now enter image description here

Would a deep query like this doable with Firestore? Or would I need to do the filtering on client side?

EDIT - added code

      // TODO: filter events to only those containing friends

        // first get current users friend list
        firebase.firestore().doc(`users/${this.props.currentUser.uid}`)
        .get()
        .then(doc => {
            return doc.data().friends
        }) 
        .then(friends => { // 'friends' is array of uid's here
        // query events from firestore where participants contains first friend
        // note: I plan on changing this design so that it checks participants array for ALL friends rather than just first index. 
        // but this is just a test to get it working...
            firebase.firestore().collection("events").where("participants", "array-contains", friends[0])
            .get()
            .then(events => {
                // this is giving me ALL events rather than 
                // filtering by friend uid which is what I'd expect
                console.log(events)
                // update state with updateEvents()
                //this.props.dispatch(updateEvents(events))
            })
        })

I am using React-Native-Firebase

"react-native": "^0.55.0",
"react-native-firebase": "^4.3.8",
Eric Furspan
  • 742
  • 3
  • 15
  • 36
  • Don't paste the image. Paste your code snippet – yogkm Sep 17 '18 at 22:37
  • Added code snippet @yogkm – Eric Furspan Sep 18 '18 at 02:37
  • It'd be easier, if you can add `participants` as a collection to the `event` document, while each document in the `participants` collection would have an id as the `uid`. Then you can query the events collection for matching `uid` in the `participants` collection inside the `event` document. You can avoid the `participants` array inside the `event` document. – Neelavar Sep 18 '18 at 05:56
  • Thanks @Neelavar good advice, I did that and now am able to query the sub collection – Eric Furspan Sep 18 '18 at 18:56

1 Answers1

0

Was able to figure this out by doing what @Neelavar said and then changing my code so that it chains then() within the first level collection query.

            // first get current users' friend list
            firebase.firestore().doc(`users/${this.props.currentUser.uid}`)
            .get()
            .then(doc => {
                return doc.data().friends
            })
            // then search the participants sub collection of the event
            .then(friends => {
                firebase.firestore().collection('events')
                .get()
                .then(eventsSnapshot => {
                    eventsSnapshot.forEach(doc => {
                        const { type, date, event_author, comment } = doc.data();
                        let event = {
                            doc, 
                            id: doc.id,
                            type,
                            event_author,
                            participants: [],
                            date,
                            comment,
                        }
                        firebase.firestore().collection('events').doc(doc.id).collection('participants')
                        .get()
                        .then(participantsSnapshot => {
                            for(let i=0; i<participantsSnapshot.size;i++) {
                                if(participantsSnapshot.docs[i].exists) {
                                    // if participant uid is in friends array, add event to events array
                                    if(friends.includes(participantsSnapshot.docs[i].data().uid)) {
                                        // add participant to event
                                        let { displayName, uid } = participantsSnapshot.docs[i].data();
                                        let participant = { displayName, uid }
                                        event['participants'].push(participant)
                                        events.push(event)
                                        break;
                                    }
                                }
                            }
                        })
                        .then(() => {
                            console.log(events)
                            this.props.dispatch(updateEvents(events))
                        })
                        .catch(e => {console.error(e)})
                    })
                })
                .catch(e => {console.error(e)})
            })
Eric Furspan
  • 742
  • 3
  • 15
  • 36