简体   繁体   中英

Two constraints on one key in a Parse Query

I'm using Parse and my app is written in Swift. I have a golf app that allows a user to friend other users. The users can log their golf scores and then see their golf scores and their friend's scores in a leaderboard style tableViewController.

The problem I'm having is that Parse doesn't support two constraints on the same key in a query. I have a function that queries the users and their scores and stores them in an array of tuples (leadeboardData). I'm trying to querying the current user's PFRelation as well as the current user (variable "friendsRelation" and constant "friendQuery"). The class I query is the "GolfScorecard", which is where the scores are stored on Parse. I then called the "whereKey" method on the "golfer" key, which is where my user is stored under on Parse. I call "whereKey matchesQuery" for my friendsRelation query and then "whereKey equalTo" to try and get my current user. I then "includeKey" "golfer" so I can get the user info along with the score info. Any suggestions on how to go about this? I'm trying to do it all in one query but when the "whereKey" method is called on the same key ("golfer") the last one overrides the first one, which makes it only possible to get the friend info or the current user info but not both. I'm stumped how to include both. Thanks in advance.

Here is my function I call to make the query:

 func loadLeaderboardData() {
    leaderboardData.removeAll()

    friendsRelation = PFUser.currentUser()?.objectForKey("friendsRelation") as? PFRelation
    friendsRelation = PFUser.currentUser()?.objectForKey("friendsRelation") as? PFRelation
    let friendQuery = friendsRelation?.query()
    let query = PFQuery(className: "GolfScorecard")
    query.whereKey("golfer", matchesQuery: friendQuery!)
    query.whereKey("golfer", equalTo: PFUser.currentUser()!)
    query.includeKey("golfer")
    query.orderByAscending("score")
    query.findObjectsInBackgroundWithBlock { (scoreCards: [PFObject]?, error: NSError?) -> Void in
        if error == nil {

                for object:PFObject in scoreCards! {
                    let golfer:PFObject = object["golfer"] as! PFObject
                    self.leaderboardData.append(object,golfer)

                    dispatch_async(dispatch_get_main_queue()) {

                    self.leaderboardTableView.reloadData()
                    }
                }

        } else {
            print(error)
    }
  }
 }

Thanks Paulw11 the orQueryWithSubQueries worked. The only issue it ended up presenting was my app was crashing with an error stating 'Key "username" has no data. Call fetchIfNeeded before getting its value.'...I don't think the Parse Query was coming back in time to load in the tableView that I was putting the data in. I ended up using the 'fetchIfNeededInBackgroundWithBlock' method inside of the cellForRowAtIndexPath call around the code where I was calling the 'username' data at. This allowed it to grab the data in the background if it didn't come back in time. This seemed to due the trick.

-Also I subclassed my queries, which is where the GolfScorecard & GolferProfile is coming from inside of my for-in loop.

-This is my new compound Query:

 func loadLeaderboardData() {
    leaderboardData.removeAll()

    friendsRelation = PFUser.currentUser()?.objectForKey("friendsRelation") as? PFRelation
    let friendQuery = friendsRelation?.query()
    let friendScorecardQuery = PFQuery(className: "GolfScorecard")
    friendScorecardQuery.whereKey("golfer", matchesQuery: friendQuery!)
    let currentUserScorecardQuery = PFQuery(className: "GolfScorecard")
    currentUserScorecardQuery.whereKey("golfer", equalTo: PFUser.currentUser()!)
    let subQuery = PFQuery.orQueryWithSubqueries([friendScorecardQuery, currentUserScorecardQuery])
    subQuery.orderByAscending("score")
    subQuery.findObjectsInBackgroundWithBlock { (scoreCards: [PFObject]?, error: NSError?) -> Void in
        if error == nil {

        for object:PFObject in scoreCards! {
            if let object = object as? GolfScorecard {
            let golfer = object["golfer"] as! GolferProfile
            self.leaderboardData.append(object,golfer)

                dispatch_async(dispatch_get_main_queue()) {

                    self.leaderboardTableView.reloadData()
                }

            }

            }

        } else {
            print(error)
    }
   }
 }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM