NSPredicate for searching within relationship entities - iphone

I have an entity called Band which has a to-many relationship to a Category entity. The Category entity just contains a categoryName string attribute.
An example record:
Band:
bandName: Kiss
bandCategories: - > BandCategory:categoryName:Glam
- > BandCategory:categoryName:Rock
How would I use NSPredicate to search thru all my Bands for bands which match the Rock category, for example?

According to the NSPredicate Programming Guide you will need to specify the key path to categoryName with the ANY or ALL specifier.
NSString *category = #"Rock";
[NSPredicate predicateWithFormat:#"ANY bandCategories.categoryName == %#", category];

Related

NSPredicate for one-to-many relationship

Assuming a Department entity and an Employee entity with a one-many relationship
Assuming relationship called employees on Department and department on Employee
Assuming Employee has an attribute name
I need to fetch all Departments that don't have an Employee called "Bob"
Based on other answers on SO that I've read, I've tried this:
name = #"Bob";
predicate = [NSPredicate predicateWithFormat:#"ALL employees.name != %#", name];
but it doesn't seem to work. Any ideas?
Thanks.
Do do not need a subquery here:
name = #"Bob";
predicate = [NSPredicate predicateWithFormat:#"NOT ANY employees.name == %#", name];
For some reason, the "ALL" aggregate does not work with to-many relationships, but the "ANY" aggregate works.

NSPredicate to query parent and child

I have a data model setup with three entities, Course, Student, TestScores.
They are linked in too-many relationships like this:
Course <---->> Student <---->> TestScores
So a Course would have several Students, who in turn could have several TestScores (or no test scores)
The Course entity has a Name attribute. TestScores is a simple entity which just contains a testScore int attribute.
I want to be able to get an array of Students who have at least one textScore of 100, ordered by Course name. Is this possible with NSPredicate?
I think you could have your predicate as
ANY testScores.score == 100
Then put it all together in a fetch request:
NSFetchRequest *req = [NSFetchRequest fetchRequestForEntityNamed:#"Student"];
req.predicate = [NSPredicate predicateWithFormat:#"ANY testScores.score == 100"];
req.sortDescriptors = [NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:#"course.name" ascending:YES]];

Using NSPredicate to filter on both Core attribute and entity

I have two entities in core data (call them entityOne and entityTwo). I have a entityOne<--->>entityTwo relationship between them.
I am now trying to code an NSPredicate to fetch entityTwo objects on the following basis:
Fetch entityTwo objects that have a relationship with a specified entityOne object.
Filter out those entityTwo objects which have no value for one of their attributes.
I am best doing both of these in an NSPredicate or is there a better way?
I am trying the following:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"(attribute <> "") AND (relationship == entityOne"];
[request setPredicate:predicate];
Any pointers on coding great fully received.
You can use a Predicate like this:
[NSPredicate predicateWithFormat:#"entityOneRelationship = %# AND attribute.length > 0",specifiedEntityOne];
Pretty common approach to do that.

NSPredicate for fetching keywords that are in a string

In core data I have an entity called keyword with a property 'text'. I want to find all keyword objects that are contained in a particular sting.
I tried:
[NSPredicate predicateWithFormat:#"%# contains[c] text", myString];
But that crashes. It seems like if it will only work if it's reversed.
The predicate works on the entity, so you have your predicate reversed. Since your entity's text property contains a single word, you'd split the string into multiple words and then test:
// This is very simple and only meant to illustrate the property, you should
// use a proper regex to divide your string and you should probably then fold
// and denormalize the components, etc.
NSSet* wordsInString = [NSSet setWithArray:[myString componentsSeparatedByString:#" "]];
NSPredicate* pred = [NSPredicate predicateWithFormat:#"SELF.text IN %#", wordsInString];
I think you're doing in reverse direction.
Try this.
[NSPredicate predicateWithFormat:#"text contains[cd] %#", myString];

What's better way to build NSPredicate with to-many deep relationships?

I have three entities: EntityA, EntityB and EntityC connected with to-many relationships.
See schema for details:
alt text http://img706.imageshack.us/img706/9974/screenshot20091220at124.png
For getting all instance of EntityA which depend from EntityB.name I use the predicate like this:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"ANY EntityB.name like 'SomeName'"];
What should be predicate for getting all instance of EntityA which depend from EntityC.name?
I tried query like #"ANY EntityB.entitiesC.name like 'SomeName'" but get exception "multiple to-many keys not allowed here".
Best regards,
Victor
My final solution is to use SUBQUERY.
NSPredicate *p = [NSpredicate predicateWithFormat:#"(name like %#) AND (0 != SUBQUERY(entitiesB, $x, (0 != SUBQUERY($x.entitiesC, $y, $y.name like %#).#count)).#count)", nameA, nameC];
Unfortunately I was unable to expand this query on nsExpression objects.
While I was stopped at the following decision:
First, I get all the EntityC that satisfy the condition EntityC.name equal to 'SomeName'
NSPredicate *p = [NSPredicate predicateWithFormat:#"name like %#", #"SomeName];
...
NSArray *res = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
Then I get an array of EntityB from above query
NSArray *parentBs = [res valueForKeyPath:#"#distinctUnionOfObjects.parent"];
Than get array of EntityB that satisfy the condition EntityB.EntitiesC.name equal to 'SomeName':
NSExpression *leftExpression = [NSExpression expressionForEvaluatedObject];
NSExpression *rightExpression = [NSExpression expressionForConstantValue:parentBs];
NSPredicate *p = [NSComparisonPredicate predicateWithLeftExpression:leftExpression rightExpression: rightExpression modifier:NSDirectPredicateModifier type:NSInPredicateOperatorType options:0];
I repeat the same for EntityA.
The effectiveness of this solution in doubt and I still expect a better solution for this problem.