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

1

1

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.

Shamrock answered 13/8, 2012 at 13:0 Comment(4)
A group has many enrollments, so what do mean exactly by "mode of the enrollments in the group = 0" ?Cirrostratus
I need to apply the filter on enrollment.mode too so that it will reflect the over all result.Shamrock
As I said, a group has multiple enrollments if I read the diagram correctly. Do you mean "mode = 0 for all enrollments of the group"?Cirrostratus
YES group.mode = 0 and enrollment.mode = 0Shamrock
C
6

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.

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];
Cirrostratus answered 13/8, 2012 at 13:24 Comment(14)
can we do (ALL enrollments.mode = 0) ??? The problem I have is , I dont know how to access the nested objects attribute.Shamrock
I would not give this answer I were not fairly confident that it is correct. YOU should try now if it works. If it works: Fine, accept my answer. If not: Show your code and ask again.Cirrostratus
You could also have a look at the Predicate Programming Guide. It has examples like "ALL children.age > 12" at the very beginning.Cirrostratus
this guy says you cant refer to child entity name #1579837Shamrock
That was a completely different question! You don't have any child entity here and you don't need the entity name in the fetch request. You have an entity "Group" and another entity "Enrollment" with a one-to-many relationship between them.Cirrostratus
When i will do group.enrollments(NSSet) it will return me a list of all the enrollments in a particular group. And then I can get any "Enrollee". Isn't it a kind of accessing a child "Entity" ? So what do I expect is that I cant apply (ALL enrollments.mode = 0) because of 2 reasons... 1 enrollments is a set so it doesnt have any attribute "mode" whereas the objects it contains are kind of ENROLLMENT and have attribute "mode". 2 In the above "comment link", it some how says that i can apply predicate on one entity(Group) and cant apply on the other Child entity(Enrollment) somehow...Shamrock
Yes, "enrollments" is a set. And "(ALL enrollments.mode = 0)" means: Give me the groups where mode=0 for ALL enrollments of this set. - I have tried to give an answer to your vaguely formulated question. It does not help if you argue why my answer might be wrong WITHOUT TRYING ANYTHING YOURSELF. So PLEASE: Start coding and try to use the predicate that I gave in my answer. If it does not work: SHOW US YOUR CODE, describe the entities and relations PRECISELY, and show us what results you got and what results you expect.Cirrostratus
Thankyou so much 4 spending time on my problem. I m not here to argue or fight :). Its vague might be I am still not clear to you. I hav tried & implemented ur solution but the app crashes due to this predicate. Wat code do u want me to show u? I hav uploaded the picture and this is the only relation between group & enrollment nothing more than that. If i ignore AND (ALL enrollments.mode = 0) the results give me all groups with 0 mode but if i add "AND (ALL enrollments.mode = 0)" the app crashes with this msg "'NSInvalidArgumentException', reason: 'Unsupported predicate (null)' "Shamrock
@yunas: You are right, "(ALL enrollments.mode = 0)" throws an exception. This seems to be a bug. But there is a workaround, see my updated answer. I hope that this will help.Cirrostratus
The predicate worked fine this time without any exception or error :), but the result is not what it was desired. Means it returns me a group if it has any active enrollment ("NOT(ANY enrollments.mode != 0)") , but required result is return me group with only active enrollments (considera group "GROUPA" EnrolA.mode = 0, EnrolB.mode = 0 , EnrolC.mode = 1), the above predicate will return me GROUPA with all Enrollments A,B,C where as required is A,B ; hope this time i am more clear and yea one more thing to be added in the predicate is to sort the enroles on attribute 'share'Shamrock
@yunas: I think a understand finally what you want. That can not be done with a query on "Group" because the fetch request returns the groups as they are in the database. Perhaps you should do a query on the "Enrollment" entity: "mode = 0 and group.mode = 0".Cirrostratus
i am really thankful to you for spending time in solving and understanding what I am stuck into. I can't do query on ENROLLMENT because the desired result is in group form and then the group shows the enrollment. Hmmm... I am thinking that it can be done in 2 ways... 1 SUBQUERY (#9968913) 2 Your solution query on "ENROLLMENT" and a "GROUPBY" thing in the predicate ?Shamrock
@yunas: A fetch request cannot return two different types of entities. I don't think that SUBQUERY helps here. - As far as I know, NSPredicate does not understand "GROUPBY". - Perhaps you can try to describe more precisely what the result should look like and what you want to do with the result. Do you want to present it in a table view? What should the table look like?Cirrostratus
let us continue this discussion in chatCirrostratus

© 2022 - 2024 — McMap. All rights reserved.