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

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.

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

CoreData - NSPredicate results if relationship has 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.

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

How can I use NSPredicate to filter on core data relationships?

Say I have core data objects of type "obj" that has a property "propertyA" and a one-to-many relationship with an object of type "sub" that has two properties, "propertyB" and "propertyC".
I want to fetch all the objs that have propertyA equal to a value and a sub obj with propertyB and propertyC set.
If it was just propertyA and propertyB, I would do
[NSPredicate predicateWithFormat:#"ANY sub.propertyB = %# AND propertyA == %#", ...];
The problem is that I can't figure out how to add in the second property. I want only the objs that have at least one sub that has the two properties true. I've tried the following, but it doesn't work:
[NSPredicate predicateWithFormat:#"ANY (sub.propertyB = %# AND sub.propertyC) AND propertyA == %#", ...];
I've tried it without the ANY but that doesn't work either. How can I do this?
Since you have a to-many relationship with the sub object, the subs property of obj returns a set instead of a single object. To query the set, you need to use a SUBQUERY.
Subqueries have the form:
SUBQUERY(collection, $individualCollectionItem, expression-with-collection-item)
in this case you would want something like
SUBQUERY(subs,$s,$s.propertyB==%#) AND SUBQUERY(subs,$s,$s.propertyC!=NULL)
The solution seems to be:
[NSPredicate predicateWithFormat:#"propertyA == %# AND (SUBQUERY(sub, $s, $s.propertyB == %# AND $s.propertyC == %#).#count != 0)", propertyAvalue, propertyBvalue, propertyCvalue];
where the values at the end are the values you want the various properties to be equal to.

Resources