Parse query retrieve pointer columns - ios

I have a Filter class which has a pointer to a user in my User class. I'm wondering how can I get the Filter object in the Filter class which is equal to the [PFUser CurrentUser] and then get both column values from the User and Filter class
PFQuery *filterQuery = [PFQuery queryWithClassName:#"Filter"];
filterQuery.limit = 1;
[filterQuery whereKey:#"userId" equalTo:[PFUser currentUser].objectId];
[filterQuery findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if(!error){
NSLog(#"%#", objects);
}
}];

You just use the object itself...
PFQuery *filterQuery = [PFQuery queryWithClassName:#"Filter"];
filterQuery.limit = 1;
[filterQuery whereKey:#"userId" equalTo:[PFUser currentUser]]; //no need to put objected here.
[filterQuery findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if(!error){
NSLog(#"%#", objects);
}
}];
As long as the userId field is a pointer to the _User object then this will work.
If userId is a pointer to _User then you can add...
[filterQuery includeKey:#"userId"];
This will then populate the userId object of the Filter objects with data when they are sent down. If you don't put that line then you will just get the objectId in the userId object.
However, I'm not sure you've done it as a Pointer. Can you confirm that it definitely is.
You should have this in the Data Browser table for Filter...
(follower will say userId on yours)

Related

IOS Parse is my nested query a good solution for comparing an object with a pointer?

Currently, I am querying the database twice to achieve a list of all users nearby who are not already being followed by the current user. Here is my nested query:
// List of all users being followed by the current user
PFQuery *followingActivitiesQuery = [PFQuery queryWithClassName:kFTActivityClassKey];
[followingActivitiesQuery whereKey:kFTActivityTypeKey equalTo:kFTActivityTypeFollow];
[followingActivitiesQuery whereKey:kFTActivityFromUserKey equalTo:[PFUser currentUser]];
[followingActivitiesQuery setCachePolicy:kPFCachePolicyNetworkOnly];
[followingActivitiesQuery includeKey:kFTActivityToUserKey];
[followingActivitiesQuery findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
NSMutableArray *followedUserIds = [[NSMutableArray alloc] init];
// Obtain an array of object ids for all users being followed
for (PFObject *object in objects) {
PFUser *followedUser = [object objectForKey:kFTActivityToUserKey];
[followedUserIds addObject:followedUser.objectId];
}
PFGeoPoint *geoPoint = [[PFUser currentUser] objectForKey:kFTUserLocationKey];
// List of all users within 50 miles that are not already being followed
PFQuery *followUsersByLocationQuery = [PFQuery queryWithClassName:kFTUserClassKey];
[followUsersByLocationQuery whereKey:kFTUserObjectIdKey notEqualTo:[PFUser currentUser].objectId];
[followUsersByLocationQuery whereKey:kFTUserLocationKey nearGeoPoint:geoPoint withinMiles:50];
[followUsersByLocationQuery whereKeyExists:kFTUserLocationKey];
[followUsersByLocationQuery whereKey:kFTUserObjectIdKey notContainedIn:followedUserIds];
[followUsersByLocationQuery setLimit:100];
[followUsersByLocationQuery findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
self.objects = objects;
[self.tableView reloadData];
}
}];
}
}];
My question is, is this a viable solution? I feel guilty about having to query the server twice in order to achieve this, but I was not able to do it all in one query. I could not compare a parse pointer from the ActivityClass to the Users class, since the Users class is the class being pointed to, and because of this I couldn't think of a way to do it all in one query.
You're in luck - this can be done in a single query using the whereKey:doesNotMatchKey:inQuery: method of PFQuery.
Parse will treat this as a single, compound query against the database. Totally guilt-free :)
Try this instead:
// List of all users being followed by the current user
PFQuery *followingActivitiesQuery = [PFQuery queryWithClassName:kFTActivityClassKey];
[followingActivitiesQuery whereKey:kFTActivityTypeKey equalTo:kFTActivityTypeFollow];
[followingActivitiesQuery whereKey:kFTActivityFromUserKey equalTo:[PFUser currentUser]];
[followingActivitiesQuery setCachePolicy:kPFCachePolicyNetworkOnly];
[followingActivitiesQuery includeKey:kFTActivityToUserKey];
PFGeoPoint *geoPoint = [[PFUser currentUser] objectForKey:kFTUserLocationKey];
// List of all users within 50 miles that are not already being followed
PFQuery *followUsersByLocationQuery = [PFQuery queryWithClassName:kFTUserClassKey];
[followUsersByLocationQuery whereKey:kFTUserObjectIdKey notEqualTo:[PFUser currentUser].objectId];
[followUsersByLocationQuery whereKey:kFTUserLocationKey nearGeoPoint:geoPoint withinMiles:50];
[followUsersByLocationQuery whereKeyExists:kFTUserLocationKey];
//The next line is your new compound query
[followUsersByLocationQuery whereKey:kFTUserObjectIdKey doesNotMatchKey:#"objectId" inQuery:followingActivitiesQuery];
[followUsersByLocationQuery setLimit:100];
[followUsersByLocationQuery findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
self.objects = objects;
[self.tableView reloadData];
}
}];

How to call data from parse in IOS?

I am trying to retrieve data from parse but I keep getting a not found on object of type PFObject for startingBalance.
Here is my code:
PFQuery *query = [PFQuery queryWithClassName:#"Account"];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
for (PFObject *object in objects) {
NSLog(#"%#", object.startingBalance);
}
}];
A PFObject is effectively an NSDictionary - at least when it comes to accessing the attributes - so you can access an attribute via objectForKey or the shorthand [] syntax -
PFQuery *query = [PFQuery queryWithClassName:#"Account"];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
for (PFObject *object in objects) {
NSLog(#"%#", object[#"startingBalance"]);
}
}];
You need to make the object a subclass of your given object type. So in this case, instead of getting an array of generic PFObject you get an array of Account objects.

Parse, query to find games of one user

In parse i have a "Game" class with array pointer column called "Players". I want to get games that contain [PFUser currentUser] in arrayKey called "Players", always this column stored a three players array.
I tried some query, i couldn't get success.
PFQuery *query = [PFQuery queryWithClassName:#"Game"];
[query whereKey:#"Players" containsAllObjectsInArray:#[[PFUser currentUser]]];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error)
{...}];
Also tried.
[query whereKey:#"Players" containsAllObjectsInArray:#[[PFUser currentUser].objectId]];
I'm sure already stored a Game with current User inside.
Thanks in advanced.
Just do this:
PFQuery *query = [PFQuery queryWithClassName:#"Game"];
[query whereKey:#"Players" equalTo:[PFUser currentUser]];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error)
{...}];
If you run equalTo on an array key, it checks to see if the value is in the array.
Make sure to check that you stored a pointer to the user, and not their objectId. If you're storing id's instead, do equalTo:[PFUser currentUser].objectId];

Parse ios wherekey using objectid

In my "Message" table in Parse I have a field called conversation, which is a pointer to a Conversation (another table in my database).
To query for a Message, can I do:
PFQuery *messageQuery = [PFQuery queryWithClassName:#"Message"];
[messageQuery whereKey:#"conversation" equalTo:_conversation.objectid];
[messageQuery findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
...
}];
or do I have to get the actual PFObject *myConversation and use that...
PFQuery *messageQuery = [PFQuery queryWithClassName:#"Message"];
[messageQuery whereKey:#"conversation" equalTo:myConversation];
[messageQuery findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
...
}];
It seems that #1 doesn't work, but #2 does...my question is how can I get #1 to work (i.e. use a PFObject's id to query when I have a pointer field)
.objectId is just a string, if your "conversation" key contains a pointer to myConversation, then you must include a PFObject in the equal to.
If you only have the objectId, you can search pointers without data using:
PFObject * myConversation = [PFObject objectWithoutDataWithClassName:#"Conversation" objectId:_conversation.objectid];
// continue here
[messageQuery whereKey:#"conversation" equalTo:myConversation];
[messageQuery findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
...
}];

Trying to query a PFRelation for a specific user in Parse

I'm trying to query a PFRelation of the current user of the app to load a table view showing all of the users friends. Each user is saved under a class called "User" when they first use the app and once they add a friend that friend is added to the column "friendsRelation" for the user. I'm using this code i got got from this link and nothing is returned from the query.
PFQuery *query = [PFQuery queryWithClassName:#"User"];
[query whereKey:#"friendsRelation" equalTo:[PFUser currentUser]];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (error) {
NSLog(#"An error occurred fetching friends");
}
else {
[self.friends addObjectsFromArray:objects];
[self.tableView reloadData];
}
}];
Try this:
PFRelation *relation = [[PFUser currentUser] relationForKey:#"friendsRelation"];
PFQuery *query = [relation query];
[query findObjectsInBackgroundWithBlock:^(NSArray *results, NSError *error) {
// results contains all friends of current user
}];
You are not query the PFUser table, so you cannot use [query whereKey:#"friendsRelation" equalTo:[PFUser currentUser]]; to query the User table, since the friendsRelation does not contain any PFUser objects but User objects. Just get the User object which represent for current user and use it to query the relation.
To Query the Users table don't use
[PFQuery queryWithClassName:#"User"];
Use instead
[PFUser query];
Only use the first if you have created your own "User" table and at this point if you checked the Data-browser you will see two different tables both called "User".

Resources