Trying to query a PFRelation for a specific user in Parse - ios

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".

Related

Getting PFObject from Parse Relation

I have a PFRelation between Users and Offers that the User saved. Each Offer has a pointer reference to a Product PFObject. Even though I am getting the Offers saved for the particular User, the Product PFObject inside the Offer PFObject is not returning completely. Below the code I tried:
PFUser *user = [PFUser currentUser];
PFRelation *relation = [user relationForKey:#“offersSaved”];
[[relation query] includeKey:#“offersSaved.product”];
The array returned from fetch contains all the offers I want, but the offers don’t contain the product PFObjects as I would like. Any suggestions?
try this:
PFUser *user = [PFUser currentUser];
PFRelation *relation = [user relationForKey:#“offersSaved”];
PFQuery *query = [relation query];
[query includeKey:#“product”];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
// ...
}];

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];
}
}];

Parse query retrieve pointer columns

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)

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];

how to query based on pfobject/pfuser associated with another pfobject in parse.com?

I have a Parse class called FriendRelation. This class has two users, one a friend the other a user.
I want to get all of the messages posted by all of the friends of a user. I am attempting to do so with the following query:
PFQuery *innerQuery = [PFQuery queryWithClassName:#"FriendRelation"];
[innerQuery whereKey:#"user" equalTo:currentUser];
PFQuery *query = [PFQuery queryWithClassName:#"Message"];
[query whereKey:#"userMessage" matchesQuery:innerQuery];
[query findObjectsInBackgroundWithBlock:^(NSArray *comments, NSError *error) {
}];
This query comes back with no results.
I believe this is occurring because of the line:
[query whereKey:#"userMessage" matchesQuery:innerQuery];
The where key needs to be a FriendRelation to match. Is this correct?
How can I make the results of the inner query be a user that will intern match the matching query?
Thanks!
You can try using
- (void)whereKey:(NSString *)key matchesKey:(NSString *)otherKey inQuery:(PFQuery *)query
Something like:
PFQuery *innerQuery = [PFQuery queryWithClassName:#"FriendRelation"];
[innerQuery whereKey:#"user" equalTo:currentUser];
PFQuery *query = [PFQuery queryWithClassName:#"Message"];
[query whereKey:#"userMessage" matchesKey:#"firendUser" inQuery:innerQuery];
[query findObjectsInBackgroundWithBlock:^(NSArray *comments, NSError *error) {
//do something useful..
}];
Let me know how it goes!

Resources