NSPredicate for obtaining all Students with a certain Course name? - ios

I have two Entities, Student and Course, where each has a to-many relationship to the other (i.e., a Student has 0 or more Courses, and a Course has 0 or more Students).
I need to obtain all Students who are enrolled in a Course. I also need to obtain all Courses in which a given Student is enrolled (by firstName).
An pseudo-predicate would be: all students who have a course whose name is equal to courseName.
So my question consists of two parts:
What is a valid NSPredicate for obtaining all students with a certain course name?
What is a valid NSPredicate for obtaining all courses where a student with a certain firstName is enrolled.
For your reference, here are my entities:

1) Use this to filter an array of students that are in a specific course with courseName :
[NSPredicate predicateWithFormat:#"ANY courses.name like %#", courseName]
Alternatively, if you already have a course object (and name is unique in call course objects), you can simply get all of its students by accessing its students property, i.e.
course.students // returns an NSSet/NSOrderedSet based on your model setup
2) Use this to filter an array of courses that have a student with a certain firstName :
[NSPredicate predicateWithFormat:#"ANY students.firstName like %#", firstName]
Note: NSSet and NSOrderedSet have a method array to get an array of the objects.
See also the docs on NSPredicate under Using Predicates with Key-Paths.

What is a valid NSPredicate for obtaining all students with a certain course name?
[NSPredicate predicateWithFormat:#"name= %#", courseName];
Use above predicate to fetch particular course while has name = courseName;Set that predicate on "Course" entity not "Student" entity.
AFter executing above fetch request, you will have array of courses having that courseName.
Course *course = [fetchedResults objectAtIndex:0];
Now to get all students in that course,
NSArray *students =[course.students allObjects];
now students is an array of "Student" entity objects.
Similarly ,
What is a valid NSPredicate for obtaining all courses where a student with a certain firstName is enrolled.
[NSPredicate predicateWithFormat:#"firstName = %#", name];
Use above predicate to fetch particular student who has name = firstName;Set that predicate on "Student" entity.
AFter executing above fetch request, you will have array of students having that firstName.
Student *student = [fetchedResults objectAtIndex:0];
Now to get all courses for that student,
NSArray *courses =[student.courses allObjects];
now courses is an array of "Course" entity objects.
Hope this helps.

Related

CoreData relationship between objects

I have two kind of objects that I retrieve from a server:
1) Companies
2) Categories
I am updating the data from the server each time that the app is become active(deleting the old data and inserting the new data). From my database Categories and Companies are connected between them with the category_id.
My question here is can I connect with a relationship each company with a category using the category_id?
I assume that means that each Company has a relationship with only one particular Category.
You want to add categoryId to your Category entity, and save the ID when you add the category.
Your models would include a number of other attributes, but here is how the relationships would be setup.
And, the relationships in the inspector...
Of course, you should specify any other options as you deem necessary.
Now, you set the category relationship of a Company entity by searching for the Category based on CategoryId, and then simply setting the category relationship. Core data will automatically take care of the inverse relationship.
Now, given any Category, you can know all the Company objects that are in that category with the `categories relationship, and given any Company you can know which Category it is in.
To fetch a Category by ID, you could do something like this...
- (NSManagedObject*)categoryWithCategoryId:(NSString*)categoryId
inMOC:(NSManagedObjectContext*)moc
error:(NSError **)error {
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:#"Category"];
fetchRequest.predicate = [NSPredicate predicateWithFormat:#"categoryId = %#", categoryId];
fetchRequest.fetchLimit = 1;
return [[moc executeFetchRequest:fetchRequest error:error] firstObject];
}
And to set the relationship, if you have xcode/mogenerator generated subclasses, just set the relationship property.
NSError *error = nil;
Category *category = [self categoryWithCategoryId:categoryId inMOC:moc error:&error];
if (category) {
// If you have generated subclasses...
company.category = category;
// Otherwise, you can do...
[company setValue:category forKey:#"category"];
}

Core data predicate on one-to-many relationship with contains

In my Core Data model, I have Conversation class, that has a 'participants' relationship, elements of which are instances of Participant class. Participant class has an href field that is a string.
Using MagicalRecord, I'm trying to fetch all Conversation instances that have at least one participant whose href contains '/businesses/%#', where %# is a given identifier. In business terms, that means loading all the conversations in which a business with a given identifier is a participant.
Here is the code that is supposed to do the fetching:
NSPredicate *participationFilter = [NSPredicate predicateWithFormat:#"ANY participants.href contains[cd] '/businesses/%#'" argumentArray:#[identifier]];
NSArray *conversations = [Conversation MR_findAllWithPredicate:participationFilter];
But conversations is always empty, even though I know that such conversations are in my database. What am I doing wrong?
'...' in a predicate is taken as a literal string, and the %# placeholder inside the
quotation marks is not expanded. You have to build the combined string first:
NSString *searchTerm = [NSString stringWithFormat:#"/businesses/%#", identifier];
NSPredicate *participationFilter = [NSPredicate predicateWithFormat:#"ANY participants.href contains[cd] %#", searchTerm];

CoreData - Fetch request with relationship object

please confirm if i understand that right...
Imagine there is an entity 'person' and an entity 'credit_card'.
So one 'person' can have many 'credit_card's.
The person entity has the attributes: name: STRING and age: INT
and relationship: creditcards (to many) inverse
and the credit card entity has: card_number: INT and valid_date: DATE and relationship: card_user (to one) inverse
In my code i have a specific person (ManagedObject) called f.e. Person *currentUser. If i now want to get all credit cards of this specific person with a specific 'valid_date' i would create a fetch request (for Entity 'credit_card') with following predicates:
NSPredicate *predicate1 = [NSPredicate predicateWithFormat:
#"valid_date == <NSDate object>"];
NSPredicate *predicate2 = [NSPredicate predicateWithFormat:
#"ANY card_user like currentUser"];
This predicate works well for me, but is that the right way? Should i really ask for: "ANY relationship name like ManagedObject" ?
If I'm understanding what you want correctly, all you need to do is use the creditcards property on your Person *currentUser and filter it down:
NSSet *setOfCreditCards = currentUser.creditcards;
NSPredicate *filter = [NSPredicate predicateWithFormat: #"valid_date == %#", date];
NSSet *cardsWithValidDates = [setOfCreditCards filteredSetUsingPredicate:filter];
The reason you tell CoreData about relationships is to avoid making another query from scratch.
You do not need to use the ANY key word if you have set up you core data model correctly. Specifically Credit cards need to have a person relationship back to the person object (you should get a warning if you didn't do this). Then you could combine both predicates into one like this
NSPredicate* predicate = [NSPredicate predicateWithFormat:#"person == %# AND valid_date == %#", currentUser, valid_date];

How to use Core Data relationship?

In my app I have 3 related entities. Athlete, Exercise, and Exercise Score.
Athlete has a to-many relationship with Exercise. It's inverse is whosExercise.
Exercise has a to-many relationship with exercise score. It's inverse is whichExercise.
I want to perform a fetch request where I get all the exercise scores for an athlete. How would I get that? Do I need another relationship between Athlete and Exercise Scores, or is that redundant? If it is, how would I use exercise as a predicate for my request?
If Exercise has a relationship to Athlete, then you should be able to do something like:
[NSPredicate predicateWithFormat:#"SELF.athlete = #%", currentAthlete];
and then just:
[Exercise fetchByPredicate:currentAthletePredicate];
Should be it.
If I clearly understand, you need to select all ExerciseScore for Athlete, but Athlete does not have direct relationship with ExerciseScore table.
SLQ Query for this may looks like :
Select *
from ExerciseScore
where IDScore in (select IDScore
from Exercise
where IDExercise in ( select IDExercise
from Athlete
)
)
But in Core Data you can't operate SLQ Queries.
Try this approach.
1.Fetch all Exercise for Athlete:
NSError *error;
NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:#"Exercise"];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF.athlete = #%", currentAthlete];
request.predicate=predicate;
NSArray *athleteExercises = [self.managedObjectContext executeFetchRequest:request error:&error];
2.Iterate throughout array of Exercises to get all Exercise score for each Exercise.
NSMutableArray *allScores = [NSMutableArray arrayWithCapacity:0];;
for (Exercise *exercise in athleteExercises) {
if ([exercise.scores count]>0) {
[allScores addObjectsFromArray:[exercise.scores allObjects]; //exercise.scores must be NSSet type
}
}
allScores array now contain All ExerciseScore objects for particular Athlete.
Predicates can have key paths:
#"whichExercise.whosExercise = %#",athlete
Or, if you have the athlete already, don't do a fetch request, just get the scores via the relationship properties.

Core data many to many relationship query

Suppose two entities: EntityA and EntityB, connected by many to many relationship. Suppose the relation attributes are relatedEntityBs and relatedEntityAs respectively. And I have an NSArray of EntityB instances. I want to find all EntityA instances which have in relation all instances that are in nsarray. That is if the array is [entityB1,.....,entityBn]. Find all EntityA instances, which are related with entityB1,wntityB2 till entityBn. How can I write this kind of predicate?
This predicate should do it:
NSMutablArray *predicateArray = [NSMutableArray array];
for (int i=0;i<entityBArray.count;i++){
NSPredicate *subPredicate = [NSPredicate predicateWithFormat:#"ANY relatedEntityBs contains %#",[entityBArray objectAtIndex:i];
[predicateArray addObject:subPredicate] ;
}
NSCompoundPredicate *daddyPredicate = [NSCompoundPredicate orPredicateWithSubpredicates:predicateArray];
Basically each sub predicate checks if relatedEntityB contains a single object of the array and finally the daddyPredicate combines them all in with OR.

Resources