0

I have a value which needs to be compared with an array of values. Basically a user needs to check if it has the same item as another user. But I am struggling to solve this as how do I get the item of an array of users? Normally when you observe a value you do something like this:

Database.database().reference(withPath: "users/\(userID)/itemList").observeSingleEvent...

However, when it comes to an array of users itemList how can this be achieved if there are multiple ID's? I'd like compare a user item or items with other users item and check if they match in order to sort an array of users that have a match.

If there is already an example for this please help direct me there.

Update

This is how my data structure looks:

{
  "users": {
    "EWJGFYmVTzOiHgnq42ebhrg2fj": {
      "firstName": "Friederike",
      "itemList": [
        2: true,
        3: true,
        0: true
      ]
    },

    "C076OYmVTzOiHgnq4wPQtY2XpED2": {
      "firstName": "Ian",
      "itemList": [
        0: true,
        1: true,
        3: true
      ]
    },
    "Juoiuf0N6qNmkm32jrtu6X6UK62": {
      "itemList": [
        0: true
      ],
      "firstName": "Jack"
    }
  }
}

Update 2.0

With the answer below I am able to query through the items table but still unable to query the keys that match as there can be multiple arrays and therefore I cannot use it to filter or anything.

2
  • To do this your probably have to adjust your data structure. Please post it so I can help. Commented Jan 9, 2018 at 11:47
  • @DoesData please see updated question. So basically you are user Juoiuf0N6qNmkmUM4qYlM6X6UK62 and you want to only query users with an itemList that matches yours. Commented Jan 9, 2018 at 14:42

1 Answer 1

1

Ok so with your current data structure you'd have to query all nodes under users and then compare the arrays, which is very inefficient. There isn't a straight forward or easy way to do that without modifying your structure. So I suggest you modify your data structure so that each item has a list of all users that have it. Something like this:

{
  "items": {
    "0": {
      "EWJGFYmVTzOiHgnq42ebhrg2fj": "Friederike",
      "C076OYmVTzOiHgnq4wPQtY2XpED2": "Ian",
      "Juoiuf0N6qNmkm32jrtu6X6UK62": "Jack"
    },

    "1": {
      "C076OYmVTzOiHgnq4wPQtY2XpED2": "Ian"
    },

    "2": {
      "EWJGFYmVTzOiHgnq42ebhrg2fj": "Friederike"
    }
    //....
  }
}

Depending on what you want to display you might want to store more information than just the users UID and username. You can query all the users that have the same items as you using a query like this:

let ref = Database.database().reference()
// assuming you already have the current users items stored in an array
for item in items {
    ref.child("items").child(String(item)).observeSingleEvent(of: .value, with: { snap in
        for child in snap.children {
            let child = child as? DataSnapshot
            if let key = child?.key, let name = child?.value as? String {
                // do something with this data
            }
        }
    })
}

Firebase database is noSQL, so data is meant to be denormalized or duplicated so that queries can be optimized. Firebase actually recommends that you avoid nesting data. Take a look at this question for more information.

Hope that helps

Code related to question asked in comments

Assuming you are storing the UID's or names of users with the same items in a string array you can prevent duplicates using .contains()

var namesWithMatchingItems = [String]()

if !namesWithMatchingItems.contains(nameYouJustFetched) {
    namesWithMatchingItems.append(nameYouJustFetched)
}
Sign up to request clarification or add additional context in comments.

12 Comments

Very helpful. Are you suggesting I have a separate table of the items value and users that have items? Also, how would storing the items to the user look like on your data structure?
Storing the items to the user doesn't change. You just create the structure above so that each item also has a list of all the users who have it. Remember we are duplicating data. Then you retrieve the user's items stored at "users"->"uid"->"items", iterate over that list and for each item retrieve the users that also have that item. That's how my query above is designed.
I've just been attempting your solution. Just wondering, is it better to save the user to item as items > 0 > users > uid instead of your example which is items > 0 > uid. That way when I loop to the item to get it's name, I'm not getting all the users ID.
They why you implement this depends on what information you want to get. I don't really have any idea what information you're storing or why. You should modify the data structure so it fits your needs without making things too complex.
I understand, I'm thinking this structure might not work for me as let's say the user removes the item from their list then it'll also have to check through the items table.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.