NSPredicate Aggregate Operations with NONE - ios

How do I create a predicate that can fetch: all questions does not contain answer.correct = "1".
The following predicate doesn't work if the returned array contain "0" and "1":
[NSPredicate predicateWithFormat:#"NONE answers.correct IN %#", [NSArray arrayWithObject:#"1"]];
Also tried with NOT (ANY ...) : same result
Is this a Bug?

Short answer: To get all objects that do not have any "answer" with "correct == 1", use the following SUBQUERY:
[NSPredicate predicateWithFormat:#"SUBQUERY(answers, $a, $a.correct == 1).#count == 0"]
Explanation: Both predicates
[NSPredicate predicateWithFormat:#"NONE answers.correct == 1"]
[NSPredicate predicateWithFormat:#"NOT (ANY answers.correct == 1)"]
should work (as I understand the NOT and ANY keywords) but they don't.
They return the same result set as
[NSPredicate predicateWithFormat:#"ANY answers.correct != 1"]
as can be seen by setting the launch argument -com.apple.CoreData.SQLDebug 3 and inspecting the SQL select statements.
This seems like a Core Data bug to me. Using the SUBQUERY is a workaround for that problem.

Related

NSPredicate to get entity of a relationship matching two conditions

I am using Core Data to fetch entities. I need to fetch only entities that have a relationship attribute that has the ID of 41 AND that same attribute needs to have the isOn property set to YES.
Here is what I am trying:
[NSPredicate predicateWithFormat:#"(SELF IN %# AND ANY attributes.attributeID.intValue == 41) AND (SELF IN %# AND ALL attributes.isOn == %#)", self.places, self.places, #YES];
For some reason this crashes my app with not explanation.
Any ideas on if my predicate format is wrong?
EDIT:
Doing more research it seems I need to use SUBQUERY but not quite sure how in this case. Here is what I tried but it also crashes with a "cannot parse format" error:
[NSPredicate predicateWithFormat:#"SUBQUERY(SELF IN %#, $e, $e.attributes.attributeID.intValue == %i && $e.attributes.isOn == %#).#count > 0)", self.places, 41, #YES]
Handle the SELF IN outside the subquery, since it relates to the entity being evaluated/fetched, not the related entity, and your SUBQUERY format is also a bit awry:
[NSPredicate predicateWithFormat:#"SELF IN %# AND (SUBQUERY(attributes, $e, $e.attributeID.intValue == %i && $e.isOn == %#).#count > 0)", self.places, 41, #YES]
Also, I'm hoping your relationship name, attributes, is just for demonstration purposes in this question. If not, I would recommend changing it. It's really confusing to have a relationship named attributes: they are mutually exclusive concepts.

NSPredicate to query many-to-many relationships

I have two Core Data classes that are related to each other with many-to-many relation. Let the classes be Item and Group, where Item.groups can reference to multiple Group, and Group.items to multiple Item objects.
I am trying to use NSPredicate to query all Item objects that do not belong to a specific Group. Using [NSPredicate predicateWithFormat:#"ANY group == %#", specificGroup] to query Item objects I can get the inverse set of what I want. It has proven hard to accomplish the opposite.
What I have tried and found not working:
[NSPredicate predicateWithFormat:#"NONE groups == %#", specificGroup] // always returns 0 results
[NSPredicate predicateWithFormat:#"NOT (ANY groups == %#)", specificGroup] // always returns 0 results
[NSPredicate predicateWithFormat:#"ANY groups != %#", specificGroup] // always returns 0 results
Any help much appreciated.

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 format specifiers issue

I use this predicate:
NSPredicate *offencePredicate =
[NSPredicate predicateWithFormat:#"(%# == %#) AND (%# == %d)", kTeamID, self.selectedTeam.teamID, kPlayerZoneID, ZoneIdTypeOffence];
but the predicate is:
"teamID" == 10 AND "playerZoneID" == 3
instead of:
teamID == 10 AND playerZoneID == 3
How can I trim this "" when I use format specifiers for predicating. And the next question is: is this the right solution using form specifiers in predicate. Because I have some API keys that are correspond to my core data entries attributes. So it is ok to use constant string that will allow quite faster changes if I need to change some of these keys, but is it ok to use this constant for predication?
You need to use %K for the keys.
It would look like this:
[NSPredicate predicateWithFormat:#"(%K == %#) AND (%K == %d)", kTeamID, self.selectedTeam.teamID, kPlayerZoneID, ZoneIdTypeOffence];
Use %K.
See this example from the documentation:
NSString *attributeName = #"firstName";
NSString *attributeValue = #"Adam";
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"%K like %#",
attributeName, attributeValue];
Result:
firstName like "Adam"

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

Resources