I have a chatroom class containing users. I can successfully query that class and return only specific PFUsers.
// get all room IDs associated with current user
var outerRoomQuery = PFQuery(className:Parse.CHATROOM_CLASS_NAME)
outerRoomQuery.whereKey(Parse.CHATROOM_USER, equalTo: PFUser.currentUser()!)
outerRoomQuery.selectKeys([Parse.CHATROOM_ROOMID])
// get all users associated with above roomIds ignoring current User
var innerRoomQuery = PFQuery(className:Parse.CHATROOM_CLASS_NAME)
innerRoomQuery.whereKey(Parse.CHATROOM_ROOMID, matchesKey:Parse.CHATROOM_ROOMID, inQuery: outerRoomQuery)
innerRoomQuery.whereKey(Parse.CHATROOM_USER, notEqualTo: PFUser.currentUser()!)
innerRoomQuery.includeKey(Parse.CHATROOM_USER)
innerRoomQuery.orderByDescending(Parse.CHATROOM_UPDATEDACTION)
innerRoomQuery.selectKeys([Parse.CHATROOM_USER])
The above query returns about 5 users.
I'm wondering if it is possible to combine these results with a separate PFUser.query() to create an OR query something like this:
var userQuery = PFUser.query()
userQuery?.whereKey(Parse.CHATROOM_USER, matchesKey:Parse.CHATROOM_USER, inQuery: innerRoomQuery) // returns nil
var receptionQuery = PFUser.query()
receptionQuery?.whereKey(Parse.USER_ROLE, equalTo:Parse.PFROLE_RECEPTIONIST) // returns around 10 receptionist users
var orUserQuery = PFUser.query()
return PFQuery.orQueryWithSubqueries([userQuery!, receptionQuery!])
The result of above only returns the receptionists. So my question is how to achieve this line:
userQuery?.whereKey(Parse.CHATROOM_USER, matchesKey:Parse.CHATROOM_USER, inQuery: innerRoomQuery)
I know this is wrong because there is no "user" (Parse.CHATROOM_USER) field in the PFUser class. I'm just wondering if there is a way to do this without firing off the roomQuery first and putting the returned PFUsers into an array and then firing the receptionist users query and combining the arrays.
Any ideas?
I'm not entirely sure what you are asking but if you are trying to have a single query find a specific type of user, i would approach this in a different fashion. I would add a bool type to the user class for what I am searching for, and just query for all the users with that bool type as true!
Related
I have a Parse Class named friendRequest where keys are requestFrom & requestTo which contains unique ids of people who have sent request and received them respectively.
I have a user for whom I need to fetch friend requests which have been sent to him and received by him to find out the status of the request.
I am trying to combine two queries where I match the user's id in requestFrom & requestTo keys and fetch all the results where the condition is true. I get 0 values in return.
My code is:
let friendsQuery : PFQuery = PFQuery(className: "friendRequest")
let objectId = PFUser.current()?.objectId
friendsQuery.whereKey("requestFrom", equalTo: objectId!)
friendsQuery.whereKey("requestTo", equalTo: objectId!)
friendsQuery.findObjectsInBackground(block: { (objects, error) in
//code
})
How should I combine the queries to get the desired results?
I am creating an application in Xcode, using swift, that is pulling information from a parse-server database (hosted by Heroku). There is a convinient way to modify the query, which can be set up, for example, as follows:
let getFollowedUserQuery = PFQuery(className: "Followers")
getFollowedUserQuery.whereKey("Follower", equalTo: (PFUser.currentUser()?.objectId)!)
However, I would like the query to query based on multiple parameters. Here it is currently only checking one column in the DB. Is there any way to modify this query using .whereKey (or something of the same sort) such that it will check multiple parameters/columns in the DB. Essentially, it will be checking these columns based on search parameters input by the user. But the user can select multiple parameters... so the query needs to return only objects which fit all parameters, not just one. Is there a way to do that?
Did you check the docs? It says:
You can give multiple constraints, and objects will only be in the
results if they match all of the constraints. In other words, it’s
like an AND of constraints.
In your case it would be:
let getFollowedUserQuery = PFQuery(className: "Followers")
getFollowedUserQuery.whereKey("Follower", equalTo: PFUser.currentUser()?.objectId ?? "")
getFollowedUserQuery.whereKey("AnotherKey1", equalTo: anotherObject1)
getFollowedUserQuery.whereKey("AnotherKey2", notEqualTo: anotherObject2)
Another option is to use NSPredicate:
let predicate = NSPredicate(format: "Follower = '\(PFUser.currentUser()?.objectId ?? "")' AND AnotherKey1 = '\(anotherObject1)' AND AnotherKey2 != '\(anotherObject2)'")
let query = PFQuery(className: "Followers", predicate: predicate)
I've two Parse tables, Users and Evaluations that are connected by a pointer reference to User.ref (a pointer to itself) -> Evaluations.evaluatedId (a user pointer)
In my PFQueryTableViewController I need to get all users list with their last evaluation. I'm trying with:
override func queryForTable() -> PFQuery
{
let userQuery = PFUser.query()!
let evaluationQuery = PFQuery(className: "Evaluations")
evaluationQuery.whereKey("evaluatorId", matchesKey: "ref", inQuery: userQuery)
let query = PFQuery.orQueryWithSubqueries([userQuery, evaluationQuery])
query.cachePolicy = PFCachePolicy.CacheThenNetwork
return query
}
But I'm getting this error:
'All sub queries of an or query should be on the same class.'
I've searched for a while and I found this:
When using orQueryWithSubqueries, each subquery should be for the same class. If you need to query different classes, you will need either a separate query for each, or use whereKey:matchesQuery: if the other class is pointed to by the parent class.
Any suggestions? Thanks in advance!
The code below queries "followers" to see if a user is following another and then if they are it queries "Post" to find post from the users they are following. Currently the logged in user is following 2 other users, user A and user B. A has 1 post and B has 2 posts. For some reason when I run the second set of codes below, it returns the counts separately. The println shows the post count by individual user. I need the count to be the sum of all posts found. It seems that there is 2 arrays of posts because there are 2 users followed. How do I combine these 2 arrays?
var getFollowedUsersQuery = PFQuery(className: "followers")
getFollowedUsersQuery.whereKey("follower", equalTo: PFUser.currentUser()!.objectId!)
getFollowedUsersQuery.findObjectsInBackgroundWithBlock { (objectos, error) -> Void in
if let objectos = objectos {
for objecto in objectos {
var followedUser = objecto["following"] as! String
var query = PFQuery(className: "Post")
query.whereKey("userId", notEqualTo: currentuser.objectId)
query.whereKey("userId", equalTo: followedUser)
query.findObjectsInBackgroundWithBlock { (objects:[AnyObject]!, error:NSError!) -> Void in
if error == nil {
self.postsArray.removeAllObjects()
self.postsFound.removeAllObjects()
let array:NSMutableArray = NSMutableArray(array: objects)
let time = dispatch_time(DISPATCH_TIME_NOW, Int64(2 * Double(NSEC_PER_SEC)))
dispatch_after(time, dispatch_get_main_queue() , { () -> Void in
fn(array)
})
} else {
println(error.localizedDescription)
}
And when I run
self.postsFound.addObjectsFromArray(array as [AnyObject])
self.totalUsers = self.postsFound.count
println("Total Posts found \(self.postsFound.count)")
The println is returning:
Total Posts found 1
Total Posts found 2
I want all the posts found to be in 1 array and have the println return:
Total Posts found 3
The best option from a query point of view would be to make only 1 query and include your followers query as a requirement of that query. In this way you would be asking for all of the posts whose author is a followed user. This is looking at the problem backwards compared to find all followed users and then find their posts. As its a composite request it's more efficient and returns a single list.
Note that there are limitations... Yhe inner query will be limited to 1000 followers (100 by default), and you would need to add a sort to get sensible results from the outer query.
Continuing with your current query setup can help you avoid these query limit restrictions, but you need to organise building a single array of results yourself. It would be best to do that in cloud code and use promises to wait for all of the requests to complete.
This is all quite general I'm afraid, but you need to decide on an appropriate approach depending on what you're actually using this data for and how many users you're expecting to have...
I have a query that gets latest posts by users. Each post has an "Owner" field that has the "ObjectId" of the account that created it. I do this because I want to also display the username of the person who created the post - which is found in the User table.
I looked at the Parse documentation for Queries and came up with this (modeled after one of their examples):
var query = PFQuery(className:"Post")
query.orderByDescending("createdAt");
var innerQuery = PFQuery(className: "User")
innerQuery.whereKey("objectId", matchesQuery: query)
Then I run the findObjectsInBackgroundWithBlock. I don't think I'm getting the information from the User table to get the name of the person who posted the post.
I looked at the object that contains the information for the post but I don't see the information for the user in that object. What am I doing wrong?
Here are screenshots of the headers of my two tables:
POST:
USER:
Thanks!
I think the problem as that you refer to the user table in the query as "PFQuery(className: "User")". But if you use the built in user table, it's name is actually "_User". So use that, or even simplier, use:
var innerQuery = PFUser.query()
Try this
var class = PFQuery(className:"Post")
var finduser:PFQuery = PFUser.query()
finduser.whereKey("objectId", equalTo: class.objectForKey("owner").objectId)
finduser.findObjectsInBackgroundWithBlock{
(objects:[AnyObject]!, error:NSError!)->Void in
if (error == nil){
if let userObjects = objects {
let UserResult = (userObjects as NSArray).lastObject as? PFUser
if let user = UserResult {
println(user.username)
}
}
}
}