PFQueryTableViewController - Getting different objects - ios

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!

Related

Compare and Match Array Values

When the user searches for a category I need all the arrays that contain that same category to appear + the other categories that are in that respective array.
Once the user has chosen ["Apples", "Oranges", "Limes"] I want to compare which array (out of many) that I queried contains Apples, Oranges or Limes. This can be one array or this can be many arrays.
These are the arrays I'm adding the values to:
var categoryNeeded = [AnyObject]() //The user creates this one and adds values to it
var categoryArr = [AnyObject]() //The Parse arrays are added here:
I have a simple Parse query function.
var query : PFQuery = PFUser.query()!
query.whereKey("contacts", containsString: "\(categoryArr)")
query.findObjectsInBackgroundWithBlock { (objects, error) -> Void in
if let objects = objects as [PFObject]! {
for object in objects {
self.categoryArr.append(object["contacts"] as! AnyObject)
print(self.categoryArr)
}
}
}
The 2nd line is suspect:
query.whereKey("contacts", containsString: "\(categoryArr)")
When querying with that line, I get this error (without a crash):
2016-01-23 15:53:47.508 CC[28514:5733236] [Error]: $regex only works
on string fields (Code: 102, Version: 1.11.0)
Without the whereKey line, I get all the values and it prints them. I just can't figure out how to compare and check for matches between the two arrays which ultimately gives the matching arrays. Is there a Swift method that does that?
You should not use containsString but rather containedIn:
query.whereKey("contacts", containedIn: categoryArr)

PFQuery where array of pointers contains a certain PFObject

Objects in my class Deal have an attribute relatedContacts which is an array of pointers to Contact objects. I'm running the following query to determine whether the current Contact object is the target of a pointer in any Deal, prior to deleting the Contact.
let relatedContactObjects:NSArray = [self.contactObject] as NSArray
let relatedContactQuery:PFQuery = PFQuery(className: "Deal")
relatedContactQuery.fromLocalDatastore()
relatedContactQuery.fromPinWithName("Deals")
relatedContactQuery.whereKey("user", equalTo: PFUser.currentUser()!)
relatedContactQuery.whereKey("relatedContacts", containsAllObjectsInArray: relatedContactObjects as [AnyObject])
However this returns Parse Error 102: "Value type not supported for $all queries."
The Parse documentation says that containsAllObjectsInArray takes an NSArray, but Xcode shows a warning that NSArray is not implicity convertible to [AnyObject].
Any ideas how I can make this query work?
Edit: I looked at the contents of relatedContacts and it seems that each instance contains an array of dictionaries, example: [{"__type":"Pointer","className":"Contact","objectId":"BoLym053hX"},{"__type":"Pointer","className":"Contact","objectId":"AgpnxAFUBn"},{"__type":"Pointer","className":"Contact","objectId":"ob20tThdfp"}]
As suggested, I've also looked at the containedIn query constraint, but that is used to identify objects that are contained in a given array. I am trying to identify arrays that contain a given object.
Parse.com overloads equalTo: by allowing it to mean either: (a) a singular property equals the operand, or (b) an array property contains the operand. So you're objective is easily stated as follows:
relatedContactQuery.fromPinWithName("Deals")
relatedContactQuery.whereKey("user", equalTo: PFUser.currentUser()!)
relatedContactQuery.whereKey("relatedContacts", equalTo:self.contactObject)
Prior to the accepted answer, I also tried using loops to go through the arrays and identify whether they contained the current object, then incremented a count.
var dealsPointingToContactCount:Int = 0
func countDealsRelatedToContact() {
let dealsWithRelatedContactQuery:PFQuery = PFQuery(className: "Deal")
dealsWithRelatedContactQuery.fromLocalDatastore()
dealsWithRelatedContactQuery.fromPinWithName("Deals")
dealsWithRelatedContactQuery.whereKey("user", equalTo:PFUser.currentUser()!)
dealsWithRelatedContactQuery.whereKeyExists("relatedContacts")
dealsWithRelatedContactQuery.findObjectsInBackgroundWithBlock{(objects, error) -> Void in
if (error == nil) {
var dealsWithPointersToContacts:NSArray = objects! as NSArray
for deal in dealsWithPointersToContacts {
var dealContactsArray:NSArray = deal["relatedContacts"] as! [PFObject]
for contact in dealContactsArray {
if contact as! PFObject == self.object {
self.dealsPointingToContactCount++
println("Deals pointing to current contact: \(self.dealsPointingToContactCount)")
}
}
}
}
}
}

Querying the User table with a users objectId queried from another table

I'm trying to query my User table with the Users objectId queried from another table.
Here's my code:
func queryFriendsTable() {
var queryFriends = PFQuery(className: "Activity")
queryFriends.whereKey("type", equalTo: "friend")
queryFriends.whereKey("fromUser", equalTo: PFUser.currentUser()!)
queryFriends.includeKey("toUser")
var queryUserTable = PFUser.query()
queryUserTable!.whereKey("objectId", matchesKey: "toUser", inQuery: queryFriends)
queryUserTable!.findObjectsInBackgroundWithBlock {
(objects: [AnyObject]?, error: NSError?) -> Void in
if error == nil {
// The find succeeded
// Do something with the found objects
if let objects = objects as? [PFObject] {
for object in objects {
self.friendNamesArray.addObject(object["username"]!)
println(self.friendNamesArray)
}
}
}
}
}
Nothing is being returned when I run this query. I think the problem has to do with the fact that the toUser objectId in the Activity table is a pointer and not a string. (The toUser value I try to use in the matchesKey spot is a pointer)
So how can I get the objectId as a string from a pointer object using the inQuery method?
Your suspicions are correct. Parse won't find pointers when looking through the User's class. Instead what you'll need to do is create a string variable and set it equal to the result of queryFriends. So what that means is you'll have to run that query first, get the pointer back, and access it's objectId field as a string in order to use it in your following query.

Parse Query where two keys equal one value

I want to perform a query that returns objects of the same value for two different keys. I can do query.selectKeys(keys: [AnyObject]) but I can't specify a value. And I can't do two separate query.whereKey(key, equalTo:) because two constraints act as an AND operator, not OR.
Any way to achieve this, or must I do two separate queries altogether?
It is possible to combine several PFQuery into a single PFQuery based on OR. A simple example can be seen here where I created a new table called ORQueries and filled it with some dummy data. Each object has a foo and a bar property which contain an integer.
func orQueryTheDummyData() {
let fooIsThreeQuery = PFQuery(className: "ORQueries").whereKey("foo", equalTo: 3)
let barIsFiveQuery = PFQuery(className: "ORQueries").whereKey("bar", equalTo: 5)
let combinedQuery = PFQuery.orQueryWithSubqueries([fooIsThreeQuery, barIsFiveQuery])
combinedQuery.findObjectsInBackgroundWithBlock { (result, error) -> Void in
println("result: \(result)")
}
}

Parse.com PFUser Query based on results from PFObject query

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!

Resources