Predicate Problem when fetching objects in a To-Many relationship - core-data

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

Related

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

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.

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.

NSFetchedResultsController predicate NOT filtering part of it (using ANY, IN and BETWEEN in the same fechRequest's predicate)

I've searched a lot here and couldn't find a solution to my situation:
I have a TableViewController that uses NSFetchedResultsController to display data from CoreData.
The model has an entity "Places" that has a to-many relationship called "Types" (and an inverse one, also to-many relationship).
In a first TableViewController I display the objects from entity "types" (each place can belong to more than one type, and one type can have more than one place). When the user taps on a row it calls a new TableViewController that will show objects from entity "Places" related to "Types" using a NSFetchedResultsController.
I know I could just use:
NSSet = [aType valueForKey:#"Places"];
However, I really want to use the NSFetchedResultsController and all its benefits.
Well, at the NSFetchedResultsController accessor method I was able to recreate this relationship by using:
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Places"
inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
NSDictionary *types = [NSDictionary dictionaryWithObjectsAndKeys:self.theTypes, #"TYPES", nil];
NSPredicate *predicateAny = [NSPredicate
predicateWithFormat:#"ANY types IN $TYPES"];
NSPredicate *predicate = [predicateAny predicateWithSubstitutionVariables:types];
This code works fine as it returns "Places" that are related to the "Types" I want (those were hold inside the property theTypes). I use a property (theTypes), in the TableViewController to hold all "Types" objects one selected at the original tableViewController.
The problem is that the entity "Places" has a property named "distance" that I also need to use as a filter inside the NSPredicate, like this:
NSNumber *radious = [NSNumber numberWithDouble:10000.00];
NSPredicate *pred = [NSPredicate predicateWithFormat:#"distance BETWEEN {0 , %#}", radious];
NSDictionary *types = [NSDictionary dictionaryWithObjectsAndKeys:self.theTypes, #"TYPES", nil];
NSPredicate *predicateAny = [NSPredicate
predicateWithFormat:#"ANY types IN $TYPES"];
NSPredicate *predicate = [predicateAny predicateWithSubstitutionVariables:types];
NSPredicate *thePred = [NSCompoundPredicate andPredicateWithSubpredicates:
[NSArray arrayWithObjects:predicate, pred, nil]];
[fetchRequest setPredicate:thePred];
Here's where the problem occurs: the "distance" filter appears to be simply ignored by the predicate at the fetchRequest. The resulted fetch always has Places that don't match the #"distance BETWEEN {0 , %#} clause.
Can anyone help me figure out what I am missing here?
Thanks a lot!
Daniel
This predicate:
NSPredicate *predicateAny = [NSPredicate
predicateWithFormat:#"ANY types IN $TYPES",
radious];
Doesn't make sense because you don't use the radious variable in this predicate. Not sure if that is the source of the problem but you should clean it up anyway.
This predicate:
NSPredicate *pred = [NSPredicate predicateWithFormat:#"distance BETWEEN {0 , %#}", radious];
... could probably be:
NSPredicate *pred = [NSPredicate predicateWithFormat:#"distance <=%#", radious];
... unless you have the possiblity of a negative radious value. It will be much faster that way.

Core Data Predicate one-to-many and many-to-one problem

I have Client entities and Job entities.
Each job can have one client. The relationship for the jobs of a client (client<-->>job) is called jobOfClient.
Each client can have many jobs. The relationship for client of a job (job<<-->client) is called clientOfJob.
(Of course, these are inverse relationships.)
I have some predicates that are working, but the last one does not. Leaving out some of the fetchedResultsController set up, here are some of the key lines of code for three cases:
Here, I sort through jobs, looking for jobs that aren't related to any client:
NSEntityDescription * entity = [NSEntityDescription entityForName:#"Job" inManagedObjectContext:dataInterface.managedObjectContext];
NSPredicate *predicate = [NSPredicate predicateWithFormat: #"clientOfJob == nil"];
Here I sort through jobs, looking for jobs of a particular client:
NSEntityDescription * entity = [NSEntityDescription entityForName:#"Job" inManagedObjectContext:dataInterface.managedObjectContext];
NSPredicate *predicate = [NSPredicate predicateWithFormat: #"clientOfJob == %#", userState.selectedClient];
But this next one doesn't work. Here I sort through clients, looking for the one client associated with a selected job (or return no result if there is no related client, but that's not the case here).
NSEntityDescription * entity = [NSEntityDescription entityForName:#"Client" inManagedObjectContext:dataInterface.managedObjectContext];
NSPredicate *predicate = [NSPredicate predicateWithFormat: #"jobOfClient == %#", userState.selectedJob];
The error message is Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'to-many key not allowed here'
There must be something subtle here that I don't understand. Can someone help me with **the info I have given?
jobOfClient will return a collection of objects, which means your predicate is essentially doing:
NSSet *jobs = [thisObject jobOfClient];
return ([jobs isEqual:aJob]);
Obviously, a collection is never equal to a single value, and so CoreData does not recognize the predicate. To get around this, I think you can do:
[NSPredicate predicateWithFormat:#"jobOfClient CONTAINS %#", [userState selectedJob]];
And to make sure you don't run into this again, I would recommend changing the name of this relationship from jobOfClient to just jobs (using the plural form to indicate it's a to-many relationship, and eliminating the OfClient, because it's already on the Client entity). Your other relationships should probably be similarly renamed. clientOfJob => client, etc.

Resources