How to use multiple ANY operators within one predicate? - ios

There are two entities C and P with a many-to-many relationship. I am trying to fetch the C entity, where C contains at least one P which consequently contains at least one C with a specific value for its attribute a.
I am trying something like this:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"ANY p.c.a = %d ", someValue];
However this obviously does not work since P has also a to-many relationship to C. I would need something like this:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"ANY p.ANY(c).a = %d ", someValue];
How would you write such predicate in the correct way?

If you want to get all C entities that have a relation to at least one P entity, then you can do that with
NSFetchRequest* request = [[NSFetchRequest alloc] initWithEntityName:#"C"];
NSPredicate * predicate = [NSPredicate predicateWithFormat:#"count(p) != 0"];
request.predicate = predicate;
assuming that p is the one-to-many relationship from C to P.

Related

CoreData predicate for one to many relationship

I have two entity: A and B.
Every element of A can have more elements of B (one to many).
Now I have an item of A and I would to take, in this item, one item B (contained in A) that it has B.field = "myParameter".
How can I generate the Predicate for this?
You may be looking for that (tested with MagicalRecord):
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"(field LIKE %#) AND (isLinkedToAObject == %#)", myFieldParameter, objectA];
With:
ClassB has a property isLinkedToAObject to link it to ClassA.

Data Retrieval With three entities without using manual looping

I have three entities.
I need to retrieve all the lectures that teach a certain student.
So far the solution i was able to come up is
first to use a subquery to retrieve all the courses the student takes by
NSPredicate *predicate = [NSPredicate
predicateWithFormat:#"SUBQUERY(students, $student, $ student.name ==
'student two').#count > 0"];
I execute the fetched request to obtain fetchedObjects.
Next i compare all the lecture objects with fetchedObjects. The lecture who conducts a course in fetchedObjects is the person who teaches the student in question.
Is there a much neater method of doing this without doing a comparison by hand ?
I mean can i do it using predicates alone?
To fetch all lecturers that have a course with the given student, use the predicate
[NSPredicate predicateWithFormat:#"SUBQUERY(courses, $c, ANY $c.students.name == %#).#count > 0", studentName]
Remark: In your first example (fetch all courses for a student), you don't need a SUBQUERY:
[NSPredicate predicateWithFormat:#"ANY students.name == %#", studentName]
Do you want to retrieve "Course" entity or "Lecturer" entities ?
for Course you could try this predicate
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"students.name = %#",NAME];
now you have Course entities and you can get Lecturers too,
for Lecturers you could try
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"ANY courses.#unionOfArrays.students.name = %#",NAME];

NSPredicate filter to-Many with child object property

I have what I thought was a simple problem. I am attempting to filter some core data where I have a Parent object which has a to-many relationship with a child object and that child object has a string id. I want to get all the parent objects where no child object has a specific id.
I have tried !(ANY... LIKE) as well as !(ANY..==) and NONE with like and == and ALL children.id != otherid
My querying looks like:
NSFetchRequest* fetchRequest = [NSFetchRequest fetchRequestWithEntityName:#"Parent"];
NSPredicate* predicate = [NSPredicate predicateWithFormat:#"NONE children.id LIKE %#",otherID];
[fetchRequest setPredicate: predicate];
NSError* error;
NSArray* allParents = [[DataManager context] executeFetchRequest:fetchRequest error:&error];
//sanity check the predicate
for (Parent* p in allParents) {
for (Child* c in p.children) {
if([c.id isEqualToString:otherID]){
NSLog(#"PREDICATE FAIL!");
}
}
}
Am I missing something with NSPredicate? Is this type of filtering allowed for CoreData? Better solution?
I found a similar question although not easily apparent. It turns out the answer is the tricky SUBQUERY. Here is what led me on the chase:
NSPredicate Aggregate Operations with NONE
and an more open explanation about SUBQUERY here:
http://funwithobjc.tumblr.com/post/2726166818/what-the-heck-is-subquery
The resulting predicate is:
//in children get a $child and group all the $child objects together
//where the ids match, if that groups count is 0 we know
//the parent has no child with that id
[NSPredicate predicateWithFormat:
#"SUBQUERY(children, $child, $child.id == %#).#count == 0",objectId];

NSPredicate for a Core Data Search

I have 3 NSManagedObjets; Person, Stuff, and Collection.
I want to use a NSPredicate to get a list of all Collections that ThePerson has.
Example: Scott has objectA and objectB which are in collection Letters and object1 which is in collection Numbers.
I want to be able to do a fetch request and get back collection Letters and Numbers.
I tried:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"ANY stuffs.persons == %#", person];
And:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SUBQUERY(stuffs, $s, ANY $s.persons == %#)", scott];
Any suggestions?
Your SUBQUERY syntax is wrong (for a full explanation, see this answer or this answer). It should be something like:
SUBQUERY(stuffs, $s, ANY $s.persons == %#).#count > 0
Since it seems that you already have a reference to a ThePerson object, you don't need to do a fetch or use a predicate. You can traverse the relationships you've declared to get the collections. You can get all of the Collections that ThePerson has by using:
NSSet *collections = [person valueForKeyPath:#"stuffs.collections"];

NSPredicate filter based on one to many values

I have 2 entities with a one to many relationship. Category represents my section headers and SubSubCategory represents my rows.
Category
{
name:string
subs<-->>SubCategory
}
SubCategory
{
name:string
numbervalue:NSNumber
}
Currently I can use NSPredicate to filter my sections based on name.
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"name==%#",#"anamevalue"];
Now I want to further filter this predicate to only return categories that have a Subcategory with a subvalue == 1.
How can I filter the Category entity based on the values in its one to many children?
I tried something like this but its no good.
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"name==%# AND subs.numbervalue==%#",#"anamevalue",1];
I'll do a predicate like the following:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"name == %# AND ANY subs.numbervalue == %#)", #"anamevalue", [NSNumber numberWithInt:1]];
The ANY is a predicate modifier that returns true only if there is at least one object in subs collection for which the comparison returns true.
The same result could be done by means of SUBQUERY.
Hope it helps.
The syntax in your predicate is wrong. You are passing an integer value as a string.
Your predicate should be
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"name==%# AND subs.numbervalue==%i",#"anamevalue",1]
Other than that it looks correct.

Resources