2

I've been trying to figure out how to get an array of users data and compare it with a list of other users array to see if it matches them. I've looked at the answer here which demonstrates that I should structure my data so that it is denormalised and therefore have duplicates. This approach works but I am now struggling to store these array into one array which can be used to later on.

Here is an example of my data structure:

{
  “skills”: [
    {
      "name": "Walking"
    },
    {
      "name": "Running",
      "usersWithSkill": [
        “user1”: true,
        “user2”: true,
        “user3”: true
      ]
    },
    {
      "name": "Swimming",
      "usersWithSkill": [
        “user3”: true
      ]
    },
    {
      "name": "Dancing",
      "usersWithSkill": [
        “user1”: true,
        “user3”: true
      ]
    }
  ],
  "users": {
    "user1": {
      "firstName": "Amelia",
      "skillsList": [
        "1": true,
        "3": true
      ]
    },
    "user2": {
      "firstName": "Elena",
      "skillsList": [
        "1": true,
      ]
    },
    "user3": {
      "firstName": "John",
      "skillsList": [
        "1": true,
        "2": true,
        "3": true
      ]
    },
    “user4”: {
      "firstName": "Jack",
      "interestsList": [
        "1": true,
        "3": true
      ]
   }
  }
}

I am able to query the interests which Jack has. However the loop happens twice and therefore I'm struggling to append an array that stores the values of the users that Jack is looking for.

This is how I query the skills:

var newArray = [String]()

func fetchSkillKeys() {

    // Loop through the array of interest keys
    for key in self.arrayOfInterestKeys {
        let interestRef = Database.database().reference(withPath: "skills/\(key)/usersSkill")
        interestRef.observeSingleEvent(of: DataEventType.value, with: { (snapshot) in
            for child in snapshot.children {
                guard let snapshot = child as? DataSnapshot else { continue }
                self.newArray.append(snapshot.key)
            }
            print(self.newArray)
        })
    }
}

This is how my array when printed on the console:

[]
["0", "1", "2"]
["0", "1", "2", "0", "1", "2"]
["0", "1", "2", "0", "1", "2", "0", "1"]

When I'm expecting something like:

["0", "1", "2", "0", "1"]

Update

Responding to the comment below, the arrayOfInterestKeys is keys taken from the interestsList which I use as a reference when querying the skills I want to observe, here is how I fetch them:

var arrayOfInterestKeys = [String]()

func fetchUserInterests() {

    guard let uid = Auth.auth().currentUser?.uid else { return }
    // Go to users interest list
    let databaseRef = Database.database().reference(withPath: "users/\(uid)/interestsList")

    // Observe the values
    databaseRef.observeSingleEvent(of: DataEventType.value, with: { (snapshot) in

        // Loop through the interests list
        for child in snapshot.children {
            guard let snapshot = child as? DataSnapshot else { continue }
            // Populate an empty array
            self.arrayOfInterestKeys.append(snapshot.key)
        }
   })
}
Chace
  • 561
  • 10
  • 28
  • 1
    What is array of keys? What values are in there when you start the query? – DoesData Jan 28 '18 at 20:03
  • please provide image for your data structure from the firebase console , also when you do this `print(self.arrayOfInterestKeys)` what output you get ? – Ali Faris Jan 28 '18 at 20:46
  • @DoesData please see the updated answer. – Chace Jan 28 '18 at 21:03
  • @Ali not sure what you mean, do you want me to take a screenshot of my firebase data structure? and `print(self.arrayOfInterestKeys)` gives me [1, 3] which is Jack's interests. – Chace Jan 28 '18 at 21:05
  • yes take screenshot of my firebase data structure – Ali Faris Jan 28 '18 at 21:07
  • Three things... First I still don't understand what array of keys is. Rather than try to explain it just show us what it is and how you got it. Second I feel like the names you are using inside your data structure are making the problem a lot more complex than it needs to be. Why are you using the numbers 0, 1, 2, 3, in multiple areas? Third the interest keys are numbers which cannot be mapped to skills because you have the skills listed as string. I don't understand what you're doing. – DoesData Jan 28 '18 at 21:09
  • @Ali, is my example not clear enough? Please see the updated question as I have made it clear which is user and which are skills – Chace Jan 28 '18 at 21:34
  • actually I don't see any wrong with your code but I can't figure out the issue you have – Ali Faris Jan 28 '18 at 21:37
  • @Ali Can you help me fetch the users that match the interests. And then save there keys into an array? – Chace Jan 28 '18 at 21:38
  • you can add `print(snapshot)` before `self.arrayOfInterestKeys.append(snapshot.key)` to see what data fetched – Ali Faris Jan 28 '18 at 21:39
  • Yes but I am getting three arrays you can see in my console. I need to put the keys into one array. – Chace Jan 28 '18 at 21:40
  • I really wish to help more but I couldn't – Ali Faris Jan 28 '18 at 21:41
  • @DoesData just to be clear the array of keys are empty arrays which I populate inside the loop. But as you can see the array happens several times. I'm trying to get just one array. – Chace Jan 28 '18 at 21:44

1 Answers1

0

You have:

for child in snapshot.children {
    guard let snapshot = child as? DataSnapshot else { continue }
    self.newArray.append(snapshot.key)
}
print(self.newArray)

Try:

for child in snapshot.children {
    let child = child as? DataSnapshot
    if let key = child?.key {
        // Make sure the key is not in the array
        if self.newArray.index(of: key) == nil {
            self.newArray.append(key)                                
        }
    }
}

Also I'd like to know how / where you are calling fetchSkillKeys()

DoesData
  • 6,594
  • 3
  • 39
  • 62
  • Not sure why you are showing me this...I am capable of getting the users interests key. I am trying to get the users that match these keys. The results are fine but how do I store the array of users that match these keys? Also, I'm calling the `fetchUserInterests()` at viewDidLoad. Are you able to chat? – Chace Jan 29 '18 at 01:00
  • I looked at the wrong code snippet, but the principle is still the same. Also where are you calling fetchSkillkeys? That's important to know.... – DoesData Jan 29 '18 at 01:06
  • That'a where I'm not too sure, I've been calling it after the interestsList loop in the `fetchUserInterests()`. Where should IO call it and where can I print this `newArray`? – Chace Jan 29 '18 at 01:09
  • It shouldn't be called until fetchUserInterests is finished. You should look into using a completion handler to determine when that's done. In any case the code above should prevent the duplicates you were seeing. – DoesData Jan 29 '18 at 01:11
  • I do believe it is to do with it being asynchronous but I have made the fetch function with completion handlers and it still doesn't work. Are you able to show me how your completion handler might work and show where you print the `newArray`? – Chace Jan 30 '18 at 19:52