2

I logged in with a Facebook account and retrieved my Facebook friends using Facebook Graph.

In my users node, when I log in for the first time, I create a new user from the info I got from Facebook log in.

As when you get the list of your friends using the app, you get a list of Facebook IDs. In order to find the user info from that facebook ID, I added a node facebookUser where I just store a list of facebook IDs as keys and with only one value, the UID of the user on Firebase.

First of all? Am I right to do so?

Let's suppose I am, how can I do to get a list of children from the node facebookUser that matches my list of Facebook IDs?

I haven't seen a method to do so. Do I have to run through my Facebook IDs list and create a reference on each child and then get the value (uid)? It doesn't seem right to me.

EDIT:

So this is the JSON of my users in the database:

  "users" : {
    "0qNPzoQysdsdsdsdycuV1rxGvQkx2" : {
      "defaultLanguage" : "en",
      "email" : "sds_tmwrhwh_asd@tfbnw.net",
      "gamesPlayed" : 0,
      "isAnonymous" : false,
      "level" : 1,
      "name" : "sds asd",
      "profileImageURL" : "https://scontent.xx.fbcdn.net/v/t1.0-1/s100x100/1371212901_469201257_n.jpg?oh=625e9f1212117c74c862a46eb&oe=5811212697",
      "providerUserID" : "10112121250247",
      "score" : 0
    }
  }

I link every user logged in with a facebook account to the facebookUsers node like this:

"facebookUsers" : {
    "10112121250247" : {
      "userID" : "0qNPzoQysdsdsdsdycuV1rxGvQkx2"
    }
  }

For the code, this is what I have done so far. I get the array of facebook IDs I got from a Facebook Graph Request, loop through them and get the corresponding UID for the facebookUsers node.

private func getUIDs(fromIDs IDs: [String]) {
        for ID in IDs {
            let ref: FIRDatabaseReference = FIRDatabase.database().reference(withPath: "facebookUsers/\(ID)/userID")
            ref.observeSingleEvent(of: .value, with: { snapshot in
                if let uid = snapshot.value as? String {
                    self.getUser(forFacebookID: ID, andUID: uid)
                }
            })
        }
    }

For each UID retrieved, I get the user node like this:

private func getUser(forFacebookID facebookID: String, andUID uid: String) {
        let ref: FIRDatabaseReference = FIRDatabase.database().reference(withPath: "users/\(uid)")
        ref.observeSingleEvent(of: .value, with: { snapshot in
            let user = User(snapshot: snapshot)
            self.facebookIdUidDic[facebookID] = user
        })
    }

This works but I have doubts about it being the best solution.

Something else: by doing this I get a lot of small asynchronous calls so to track when all the calls are done, I check the size of my facebookIdUidDic and compare it with the size of my facebook IDs array. But again, doesn't feel right.

Nico
  • 6,269
  • 9
  • 45
  • 85
  • 1
    Instead of describing your code and data structure, include the actual minimal code and JSON (both as text, no screenshots please) in your question. That will typically make your question clearer and thus make it easier to answer. – Frank van Puffelen Oct 12 '16 at 07:11
  • Thanks. That's much easier to follow. What doubts do you have about this approach? If you're worried about the performance of the client-side join: such operations are fairly standard in Firebase (and most NoSQL solutions) and not nearly as slow as you may think, because Firebase pipelines the requests. See http://stackoverflow.com/questions/35931526/speed-up-fetching-posts-for-my-social-network-app-by-using-query-instead-of-obse/35932786#35932786 – Frank van Puffelen Oct 12 '16 at 09:12
  • Yes that's mostly the reason, that there could be something more performant. How can I know when all the asynchronous calls are done? Is my way ok? – Nico Oct 12 '16 at 09:14
  • 2
    I indeed usually keep a count of the items that I need to load (e.g. `pendingItemCount`) and then decrement that as each item comes back. When there are no more pending items, I am done. An alternative is to duplicate the friend's data under each user. That leads to a lot more data storage, but simpler code. Both are valid approaches. Which one is better depends on the use-case and personal preference. – Frank van Puffelen Oct 12 '16 at 09:17
  • Okay. I'll do that. Cheers. – Nico Oct 12 '16 at 09:17

0 Answers0