Parse - Query a value in a pointer in an array - ios

If I have pointers to multiple _User objects in an array, can i query for a value of a User.
Ex.
I have a class Groups with an array members.
members = [user1, user2, user3].
Can I do something like:
PFQuery *query = [PFQuery queryWithClassName:#"Groups"];
[query whereKey:#"members.name" isEqual:#"James"];

This can be accomplished with a nested query. Create an "innerQuery" to find Users matching the criteria. Then constrain a Group query with whereKey:matchesQuery:.
PFQuery *innerQuery = [PFUser query];
// note that referring to the "name" field only makes sense if you've
// added a name field to User (you might mean username here)...
[innerQuery whereKey:#"name" isEqual:#"James"];
// now the main query is setup to match the innerQuery
PFQuery *query = [PFQuery queryWithClassName:#"Groups"];
[query whereKey:#"members" matchesQuery:innerQuery];
[query findObjectsInBackgroundWithBlock:^(NSArray *comments, NSError *error) {
}];

Related

How to access fields of a pointer's value on parse.com with iOS?

I am designing a database. According to documentation, when number of relationships are greater than 100 and there is extra fields, I must design a Join Table. I designed this Join Table by having two pointer value.
This pointer value is pointing to _User. Later I need only rows for currUser.
This pointer value is the objectId of another table which is an entity. My question is, how can I write a query to return objects for this table in queryfortable.
Let's say:
Table _User
Table Entity
Table Join ---> objectId Pointer1(_User) Pointer2(Event)
This look like this:
This is what I have tried so far:
First I tried in viewDidLoad to get array of invitedUser from cloud and later in queryForTable:
PFQuery *query = [PFQuery queryWithClassName:#"Event"];
[query whereKey:#"objectId" containedIn:_inviteList];
but I need to access _inviteList.objectId which is not possible!
I tried to use innerQuerry or relation query. but as I just started learning parse I am not able to implement this.
PFUser *friendPointer = [PFUser currentUser];
PFQuery *query2 = [PFQuery queryWithClassName:#"Event"];
[query2 whereKey:friendPointer containedIn:_inviteList];
return query2;
This also did not work for me.
PFQuery *innerQuery = [PFQuery queryWithClassName:#"Invite"];
[innerQuery whereKey:#"invitedUser" equalTo:[PFUser currentUser]];
query = [PFQuery queryWithClassName:#"Event"];
[query whereKey:#"user" matchesQuery:innerQuery];
return query;
I appreciate if anyone can help me to write this query or re-design my table in order to have access to this query.
Pleaser try this code and give me review
PFUser *user = [PFUser currentUser];
PFQuery *query = [PFQuery queryWithClassName:#"Invite"];
[query whereKey:#"invitedUser" equalTo:user];
[query includeKey:#"invitedUser"];
[query includeKey:#"eventId"];
[query orderByDescending:#"updatedAt"];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error)
{
if (error == nil)
{
for (PFObject *underobject in [objects reverseObjectEnumerator])
{
PFUser *user1 = underobject[#"invitedUser"];
NSLog(#"invitedUser is :%#",user1);
}
}
}];

Multiple whereKey:doesNotMatchKey:inQuery: in one query

I have users friendships sorted in a Friendship class with fromUser and toUser keys. When I want to only return users that are not in a friendship with the currentUser, I want to use two whereKey:doesNotMatchKey:inQuery: to sort the current friendships out.
PFQuery *query = [PFUser query];
[query whereKey:#"objectId" notEqualTo:[PFUser currentUser].objectId];
[query whereKey:#"username" hasPrefix:string];
PFQuery *fromFriends = [PFQuery queryWithClassName:parseFriendshipClassName];
[fromFriends whereKey:parseFriendshipFromUserKey equalTo:[PFUser currentUser]];
-> [query whereKey:#"objectId" doesNotMatchKey:parseFriendshipToUserIdKey inQuery:fromFriends];
PFQuery *toFriends = [PFQuery queryWithClassName:parseFriendshipClassName];
[toFriends whereKey:parseFriendshipToUserKey equalTo:[PFUser currentUser]];
-> [query whereKey:#"objectId" doesNotMatchKey:parseFriendshipFromUserIdKey inQuery:toFriends];
If I comment out either of these two lines, the other one works as expected, but if they are both there, only the last of them works.
In the Friendship table, the users are referenced both as a pointer and as their objectId. I use the objectId to reference them here, so it is not because I compare pointers to ids.
The documentation does not seem to suggest, that adding more than one would override the old one.
Is this expected behaviour? Or am I doing something wrong?
In this case you should use the orQueryWithSubqueries:. It should solve this.

Multiple Query Search with Parse.com

I'm trying to query to find specific users based on certain credentials.
The query will only look in the User class.
First, I want the query to match the currentUser's location
Second, must match a specific category (meaning multiple users in the same location may be under the same category)
Here's what I have tried:
self.profileObj = [self.currentUser objectForKey:#"city"];
PFQuery * queryOne = [PFUser query];
[queryOne whereKey:#"city" equalTo:self.profileObj];
PFQuery * queryTwo = [PFUser query];
[queryTwo whereKey:#"category" equalTo:self.tagString];
PFQuery * query = [PFQuery orQueryWithSubqueries:#[queryOne, queryTwo]];
[query orderByAscending:#"createdAt"];
[query findObjectsInBackgroundWithBlock:(NSArrayobjects, NSError error)
This is returning 0 results.
You don't need two separate queries since you are querying on the same User object. Also, I believe you want two AND constraints rather than OR? If so, you can just chain together two whereKeys:
PFQuery * query = [PFQuery queryWithClassName:#"User"];
[query whereKey:#"city" equalTo:self.profileObj];
[query whereKey:#"category" equalTo:self.tagString];
[query orderByAscending:#"createdAt"];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
...
}];

or query with include

I have a join table with a from column and a to column. Both columns point to user objects. When perform this OR query, it throws the error: 'OR queries do not support sub-queries with includes'
Is there any way around this? Thanks!
// set up query to get all relationships where the current user friended another user.
PFQuery *userIsFriendSender = [PFQuery queryWithClassName:#"UserRelationships"];
[userIsFriendSender whereKey:#"from" equalTo:[PFUser currentUser]];
[userIsFriendSender whereKey:#"active" equalTo:#YES];
[userIsFriendSender includeKey:#"to"];
// set up query to get all relationships where a use friended the current user
PFQuery *userIsFriendReceiver = [PFQuery queryWithClassName:#"UserRelationships"];
[userIsFriendReceiver whereKey:#"to" equalTo:[PFUser currentUser]];
[userIsFriendReceiver whereKey:#"active" equalTo:#YES];
[userIsFriendReceiver includeKey:#"from"];
PFQuery *query = [PFQuery orQueryWithSubqueries:#[userIsFriendSender, userIsFriendReceiver]];
Try moving includeKey: clauses to the joint query.
PFQuery *query = [PFQuery orQueryWithSubqueries:#[userIsFriendSender, userIsFriendReceiver]];
[query includeKey:#"from"];
[query includeKey:#"to"];

parse.com: How to compare pointer-keys with objects?

I am using the backend service parse.com for a iOS app and I have a problem with querying it properly. I need help with the method whereKey:matchesKey:inQuery;
I have this code:
//NOT WORKING
PFQuery *query1 = [PFQuery queryWithClassName:#"Object"];
PFQuery *query2 = [PFQuery queryWithClassName:#"ObjectsRelations"];
[query2 whereKey:#"user" equalTo:[PFUser currentUser]];
[query1 whereKey:#"objectId" matchesKey:#"objectPointer" inQuery:query2];
[query1 findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
// No objects
}];
It is not working the way I want. I have tried several ways for it to compare the key "objectPointer" in class "ObjectsRelations" (which is a pointer to an instance of class Object) to the actual Object in query 1. I do not get any objects back, because the comparison does not work as I want, since the key objectId is just a string and the key objectPointer is a pointer to a Object.
When I run this code, I get the intended result, but this requires me to do two api-requests to get the actual objectId as a string!
//WORKING
PFQuery *query = [PFQuery queryWithClassName:#"Object"];
PFQuery *query2 = [PFQuery queryWithClassName:#"ObjectRelations"];
[query2 whereKey:#"user" equalTo:[PFUser currentUser]];
[query2 findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
PFObject *firstObject = [((PFObject*)[objects firstObject]) objectForKey:#"objectPointer"];
[query whereKey:#"objectId" equalTo:firstObject.objectId];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
//Getting the objects correctly from the class Object!
}];
}];
How to do this with a single api-request? How to compare a instance of a Class to a pointer of a class with a query?
Something like this is what i want to do: (Pseudo Code)
[query1 where:SELF matches:#"objectPointer" inQuery:query2];
Any suggestions?
I just searched this exact same problem and there are a number of questions on the Parse forum regarding it:
Trouble with nested query using object_id
Assistance with relational query
Compare string to pointer in query with does not match key in query
The first one explains a hack to include an extra field (in this case) in your ObjectRelations class. This key/field would be a string that would be the objectId of the pointer. It would be in addition to the key/field that holds the pointer.
If you look through the questions you can see that as of now there doesn't seem to be an answer directly from Parse regarding this.
Instead of adding an additional column with type String to contain the objectID it points to, I would suggest to add a column on each object with type Pointer to point to the object itself. This would dramatically reduce the amount of the columns you have to add. The only downside is this must be done on Cloud Code.
At this question's scenario, you'll have two queries like:
//Inner query
//Library containing pointer<Deck> & pointer<User>
PFQuery * subscriptions = [PFQuery queryWithClassName:#"subscription"];
[subscriptions whereKey:#"User" equalTo:[PFUser currentUser]];
//Outer query
//Pull down a list of deckStore objects not included in the subscriptions for current user
PFQuery * decks = [PFQuery queryWithClassName:#"deckStore"];
Then instead of:
[decks whereKey:#"objectId" doesNotMatchKey:#"deckString" inQuery:subscriptions];
You can do this:
[decks whereKey:#"this" doesNotMatchKey:#"deck" inQuery:subscriptions];
Here's a sample of what the Cloud Code should be added:
Parse.Cloud.afterSave("Deck", function(request) {
var deck = request.object;
// To make sure this is the first time of "afterSave" of this object.
if (deck.createdAt.getTime() == deck.updatedAt.getTime()) {
// "this" is the column which contains the pointer of the object itself.
if (deck.get("this") == null) {
deck.set("this", deck);
deck.save();
}
}
}
I have the same problem. This is my solution:
PFQuery *query1 = [PFQuery queryWithClassName:#"tableClass"];
[query1 whereKey:#"objectId" equalTo:[(PFObject *)[object objectForKey:#"pointerField"] objectId]];
PFObject *obj1 = [query1 getObjectWithId:[(PFObject *)[object objectForKey:#"pointerField"] objectId]];
NSString *pointerName = [obj1 objectForKey:#"name"];

Resources