CoreData - NSPredicate results if relationship has data - core-data

I have a many-to-many relationship between tables, and I populate a tableView with Activities.
For that i user a simple NSPredicate like this:
request.predicate = [NSPredicate predicateWithFormat:#"deleted == %#", [NSNumber numberWithBool:NO]];
How can I do to show only the Activities that has Members attached to it?
I think that in the NSPredicate I have to do some count so that only the Activities with count > 0 are returned. Is that so?
How?
(i'm newbie in coredata...)
Thanks,
RL

You need to add a subquery to your predicate acting on the CompanyActivity entity as follows:
[[NSPredicate predicateWithFormat:#"deleted == %#" && (0 >= SUBQUERY(Members, $sub, $sub.deleted == %#).#count)", [NSNumber numberWithBool:NO] [NSNumber numberWithBool:NO]];
The first part of the predicate returns objects which have not been deleted, the second one related to the subquery will take care of retrieving all those CompanyActivity objects whose Members have not been deleted.

Related

Is a subquery needed for my nspredicate to work properly?

I have an array of custom objects that have beds (1,2,3), fireplace (yes or no), den (yes or no) and ceiling heights (9-11,11-14,14-16). I need to allow filtering based on any/all/none of the items being selected to filter by. So a user may want to see 1 & 2 beds, den, fireplace and 9-11 foot ceilings. Or just 1 & 2 beds. My current predicate works for some of these. But it doesn't match all - only some. I am thinking I need a subquery. How to create a nested(?) subquery based on an array of filters?
Right now, the user selects buttons and those are matched against Filters and I use those to create my predicate.
Current predicate
Filters is an array of keys and predicate strings like 'beds, 1' and 'ceilings, 9-11'
`NSMutableArray *subPredicates = [NSMutableArray array];
for (Filter*fil in filters) {
NSPredicate *unitsPredicate = [NSPredicate predicateWithFormat:#"%K == %#", fil.key, fil.predicate];
[subPredicates addObject:bedsPredicate];
}
NSPredicate *predicate = [NSCompoundPredicate andPredicateWithSubpredicates:subPredicates];
NSLog(#"homes: %#", [searchArray filteredArrayUsingPredicate:predicate]);
NSArray *ar = [searchArray filteredArrayUsingPredicate:predicate];
I'd like to allow someone to pick any of the criteria and return appropriate data.
Subqueries are used with to-many relationships. If you want to filter multiple values then the class of fil.predicate should be an array (or set) of values. The predicate format is %K IN %#, for example
for (Filter*fil in filters) {
NSPredicate *unitsPredicate;
if ([fil.predicate isKindOfClass:[NSArray class]])
unitsPredicate = [NSPredicate predicateWithFormat:#"%K IN %#", fil.key, fil.predicate];
else
unitsPredicate = [NSPredicate predicateWithFormat:#"%K == %#", fil.key, fil.predicate];
[subPredicates addObject:bedsPredicate];
}
NSPredicate *predicate = [NSCompoundPredicate andPredicateWithSubpredicates:subPredicates];
See Aggregate Operations in Predicate Programming Guide.

Core Data NSPredicate with to-Many Relationship

I have two Entities in CoreData called User and Coupon, they are in Many-to-Many relationship. I wanted to fetch for all Coupons except those owned by user.userId = 1, where userId is NSString.
I used:
[NSPredicate predicateWithFormat:#"NOT(ANY couponOwners.userId = %#)", #"4"];
to be the predicate of my fetchedResultsController
but not filtering with correct results. One of the User in couponOwners of the Coupon is still having userId = 4.
Could somebody please help? I have been stuck for quite a while. Thanks in advance.
Core Data predicates with "NOT ANY" do not work (that seem to be a Core Data bug). Actually
[NSPredicate predicateWithFormat:#"NOT(ANY couponOwners.userId = %#)", #"4"];
returns the same result set as
[NSPredicate predicateWithFormat:#"ANY couponOwners.userId != %#", #"4"];
which is of course wrong. As a workaround, you can use a SUBQUERY:
[NSPredicate predicateWithFormat:#"SUBQUERY(couponOwners, $c, $c.userId == %#).#count == 0", #"4"]

NSPredicate on nested object / NSSet to filter the result during NSFetchRequest

I want a simple predicate that returns me all the groups which have mode = 0 and the mode of the enrollments in the group = 0
To be precise i need a predicate to access the nested object properties.
Somehow a predicate like:
[NSPredicate predicateWithFormat:#"mode = 0 AND enrollments.Enrollment.mode = 0"]
the above predicate is wrong and obviously doesn't work.
EDITED:
I have given a go to the following predicate too but been unsuccessful.
[NSPredicate predicateWithFormat:#"mode = 0 AND ALL ( SUBQUERY(enrollments,$varEnrollment,$varEnrollment.mode = 0))"]
I need result which contains all groups that are active (group.mode = 0) AND with all enrollee's that are active (enrolles.mode = 0)
but for me this predicate doesn't work.
From your question and the comments I guess that you want
[NSPredicate predicateWithFormat:#"mode = 0 AND (ALL enrollments.mode = 0)"]
UPDATE
It seems that the ALL aggregate does not work. It throws
'NSInvalidArgumentException', reason: 'Unsupported predicate (null)'
as #yunas noticed. This has also been noticed previously, e.g.
Core Data, NSPredicate and to-many key
Crash using Aggregate Operation: "ALL" in a Core Data iOS Application
On the other hand, the ANY aggregate works just fine. So as a WORKAROUND, one can replace ALL with an equivalent ANY expression:
[NSPredicate predicateWithFormat:#"mode = 0 AND NOT(ANY enrollments.mode != 0)"];
And this actually works (I have tested it)!
UPDATE 2
During the discussion it has become clear that yunas wants to display a table with one row for each group with mode=0, and within the table row display all enrollments of that group with mode=0.
First solution (probably the better one): Find all admissible groups first with the method given above. For each row (in cellForRowAtIndexPath:) filter the enrollments for that group and draw the cell.
Second solution: Fetch all enrollments and sort them by group. This requires only one fetch request, but the result is not so suitable as table view data source. The fetch request would look like this:
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:#"Enrollment"];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"mode = 0 AND group.mode = 0"];
request.predicate = predicate;
NSSortDescriptor *sort1 = [NSSortDescriptor sortDescriptorWithKey:#"group.name" ascending:YES];
NSSortDescriptor *sort2 = [NSSortDescriptor sortDescriptorWithKey:#"share" ascending:YES];
request.sortDescriptors = [NSArray arrayWithObjects:sort1, sort2, nil];

Creating Core Data predicate to get data within one-to-many relationship

I have a Loans entity with a returnedDate attribute that can contain a date or be NIL. There is a to-many relationship with another entity, Items such that items can be related to many Loans. I would like to create a predicate where I can find all items that do not currently have a loans.returnedDate==NIL.
Assume I currently have the following:
Loan1-item1,returnedDate=NIL
Loan2-item1,returnedDate=5/4/2012
Loan3-item2,returnedDate=NIL.
I would like a predicate that returns no items.
NSPredicate *pred = [NSPredicate predicateWithFormat:#"!(ANY loaned.returnDate==nil)"];
Returns item1.
NSPredicate *pred = [NSPredicate predicateWithFormat:#"(NONE loaned.returnDate==nil)"];
Returns item1.
NSPredicate *pred = [NSPredicate predicateWithFormat:#"(ANY loaned.returnDate!=nil)"];
Returns item1.
Can someone tell me what logic would return the appropriate results?
So I used the following predicate:
(SUBQUERY(loaned, $sub, $sub.returnDate==nil).#count == 0)
and it is returning the desired results. If you can convince me not to use SUBQUERY, please tell me how.

Predicate Problem when fetching objects in a To-Many relationship

I have a simple situation where I have two entities related with Many-To-Many relationship.
Two objects, Alarms and Tags. When I want to fetch all the Alarms associated with a given Tag, I tried this:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"%# IN tags", theTag];
What I get is all Alarms, not just those related to the Tag.
However, trying this the other way around works:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF in %#", theTag.alarms];
For complicated reasons having to do with code reuse, I really need the first one to work. Any help would be much appreciated! Thanks!
If you have a Tag object, then you can get all of its alarms by doing:
NSSet *alarms = [theTag alarms];
If for some bizarre reason you have to do this with a fetch request (which you shouldn't), your predicate should be:
NSPredicate *p = [NSPredicate predicateWithFormat:#"tags CONTAINS %#", theTag];

Resources