How to get childs whose arrays contain a certain v

2020-05-09 01:29发布

问题:

I have a database scheme that is essentially the same that the one is the documentation :

// An index to track Ada's memberships
{
  "users": {
    "alovelace": {
      "name": "Ada Lovelace",
      // Index Ada's groups in her profile
      "groups": {
         // the value here doesn't matter, just that the key exists
         "techpioneers": true,
         "womentechmakers": true
      }
    },
    ...
  },
  "groups": {
    "techpioneers": {
      "name": "Historical Tech Pioneers",
      "members": {
        "alovelace": true,
        "ghopper": true,
        "eclarke": true
      }
    },
    ...
  }
}

I would like to create a DatabaseQuery that gets all users that take part of a specific group (for instance users whose "groups" contain "techpionneers")

How should I proceed ? I tried a Database.database().reference(withPath: "users").queryOrdered(byChild: "groups").queryEqual(toValue: "techpioneers") but that does not work (obviously).

回答1:

Franks solution is spot on but an alternative is to use a Deep Query i.e. ordering by deep paths to query the users node for child->child nodes that match the criteria. Here's the format

    let ref = self.ref.child("users")
    let query = ref.queryOrdered(byChild: "groups/techpioneers").queryEqual(toValue: true)
    query.observeSingleEvent(of: .value, with: { (snapshot) in 
        for child in snapshot.children {
            let snap = child as! DataSnapshot
            print(snap)
        }
    })

the result is all of the users that are part of the techpioneers group

"alovelace": {
   "name": "Ada Lovelace",
   "groups": {
      "techpioneers": true,
      "womentechmakers": true
      }
}


回答2:

To load all users that are part of a specific group, start in the /groups node to find their key:

ref.child("groups/techpioneers/members").observeSingleEvent(of: .value, with: { (snapshot) in

That gives you the keys of all members. Then loop over those keys and load the corresponding user.

This is essentially a client-side join operations. While you may initially think this is incredibly slow, it's actually not all that bad since Firebase pipelines the requests over a single connection. See http://stackoverflow.com/questions/35931526/speed-up-fetching-posts-for-my-social-network-app-by-using-query-instead-of-obse/35932786#35932786.