I want to make NSPredicate over different entities. Here is my core database.
To make it simple, this is the query I should do.
Select c.c_name From Company c, Person p Where c.c_id = p.cu_company_id
Now I was wondering how my predicate should look like if I want to achieve the result like the query above.
Assuming that c_id and cu_company_id are integers, you can try
NSFetchRequest *fr = [[NSFetchRequest alloc] initWithEntityName:#"Person"];
NSError *error;
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"cu_company_id == data.company.c_id"];
[fr setPredicate:predicate];
NSArray *persons = [self.managedObjectContext executeFetchRequest:fr error:&error];
and once you have persons array, you can then loop through it and get the person's name. To get it the other way around
NSFetchRequest *fr = [[NSFetchRequest alloc] initWithEntityName:#"Company"];
NSError *error;
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"c_id == data.person.cu_company_id"];
[fr setPredicate:predicate];
NSArray *companies = [self.managedObjectContext executeFetchRequest:fr error:&error];
and once you have companies array, you can then loop through it and get the company's name.
Related
I am trying to execute a fetch request on NSManagedObjectContenxt and I want the predicate to be case insensitive.
I tried several solutions that I found but all of them works only on NSArray (filteredArrayUsingPredicate) but not on Core Data.
For example:
My persistent store contains an NSManagedObject, 'Car', with the attribute 'name' and its value is "GMC".
1) The following returns with an empty array:
NSFetchRequest* fetch = [[NSFetchRequest alloc] init];
fetch.entity = [NSEntityDescription entityForName:#"Car" inManagedObjectContext:moc];
fetch.predicate = [NSPredicate predicateWithFormat:#"name matches[c] %#", #"gmc"];
NSArray* cars = [moc executeFetchRequest:fetch error:nil];
2) The following crashes with 'EXC_BAD_ACCESS':
fetch.predicate = [NSPredicate predicateWithFormat:#"name ==[c] %#", #"gmc"];
NSArray* cars = [moc executeFetchRequest:fetch error:nil];
3) The only fetch that works is:
fetch.predicate = [NSPredicate predicateWithFormat:#"name == %#", #"GMC"];
NSArray* cars = [moc executeFetchRequest:fetch error:nil];
Is it possible to do case insensitive fetch in Core Data? And how?
Thanks.
Try below code:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"UPC ==[c] %# OR ItemID ==[c] %#", aUPCCode,aUPCCode];
The keywords "like" and "contains" seem to work just fine.
fetch.predicate = [NSPredicate predicateWithFormat:#"name like[c] %#", #"gmc"];
or
fetch.predicate = [NSPredicate predicateWithFormat:#"name contains[c] %#", #"gmc"];
More keyword options and details can be found here:
https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/Predicates/Articles/pSyntax.html#//apple_ref/doc/uid/TP40001795-CJBDBHCB
and here
http://nshipster.com/nspredicate/
Use #selector(caseInsensitiveCompare:) with your fetchRequest like:
NSSortDescriptor *sortDescr = [NSSortDescriptor sortDescriptorWithKey:#"name" ascending:YES selector:#selector(caseInsensitiveCompare:)];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:#"Car"];
[fetchRequest setSortDescriptors:#[sortDescr]];
[fetchRequest setPredicate:[NSPredicate predicateWithFormat:#"name matches[c] %#", #"gmc"]];
Then perform your fetch as usual.
I have two Entity models "Content" and "LessonsContent" with no relationship between them. Both entities have common attribute "contentID" of NSNumber type. I am fetching all contents objects from "Content" entity for given predicate and storing these objects in contents array. I was successful in doing so.
Now, I want to fetch all lessonsContent objects from "LessonsContent" entity whose contentIds are present in contents array.
I am using following code:
NSPredicate * predicate = [NSPredicate predicateWithFormat:#"(contentType == %#)", #"Games"];
NSError * error;
NSFetchRequest * request = [[NSFetchRequest alloc] initWithEntityName:NSStringFromClass([Content class])];
[request setPredicate:predicate];
[request setReturnsObjectsAsFaults:NO];
NSArray *contents = [[DELEGATE managedObjectContext] executeFetchRequest:request error:&error];
if(error){ NSLog(#"Error in fatching data");}
//predicate = [NSPredicate predicateWithFormat:#"Content.contentID IN %#", contents];
predicate = [NSPredicate predicateWithFormat:#"(SUBQUERY(contents, $x, $x.Content.contentID IN %#).#count != 0)",contents];
request = [[NSFetchRequest alloc] initWithEntityName:NSStringFromClass([LessonsContent class])];
[request setPredicate:predicate];
NSArray * mappingArray = [[DELEGATE managedObjectContext] executeFetchRequest:request error:&error];
NSLog(#"mappingArray %#", mappingArray);
But app is crashing. Please suggest appropriate solution.
Thanks in advance.
You have to get an array of contentID's first. Then use IN.
NSArray *contents = [[DELEGATE managedObjectContext] executeFetchRequest:request error:&error];
NSArray * allContentIDs = [contents valueForKey:#"contentID"];
then use the second predicate
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"contentID IN %#", allContentIDs];
[request setPredicate:predicate];
Hope this helps.
I have a one to many relationship as shown in the attached image. I want to list down all the course titles a particular lecturer teaches and the solution i have come up so far is as follows.
NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:#"Lecturer"];
NSMutableSet *courseList = [[NSMutableSet alloc] init];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"name == 'smith'"];
[request setPredicate:predicate];
NSError *error = nil;
NSArray *lecturers = [self.managedObjectContext executeFetchRequest:request
error:&error];
for (Lecturer *lecturer in lecturers)
{
NSSet *set = lecturer.courses;
for (Course *course in set)
{
[courseList addObject:course.title];
}
}
The courseList object contains all the courses a given lecturer teaches.
IS there a better way to do this using nspredicates alone and not by using 2 for loops ?
Thanks in advance.
You can just fetch the Course objects directly, but specifying a different predicate that requires their authorname.name to match:
NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:#"Course"];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"authorname.name == 'smith'"];
[request setPredicate:predicate];
NSError *error = nil;
NSArray *courseList = [self.managedObjectContext executeFetchRequest:request error:&error];
If you want an array with just the titles, you can then use:
NSArray *courseTitles = [courseList valueForKeyPath:#"title"];
i used this code to select all products that related to specific category but it doesn't work ,, what is the correct predicate that i can use to get all products related to this category
NOTE:
i get the categories list from server alone and insert them ,, and then get products list from server and inserting them ,, but i figured out now that the product don't know his category ,, i'm using restkit library to parse and insert in the database ,, so how i can tell the products that the category ,, the restkit do all the work automatically
how to set to the product list thet i get from server their category ?
//--fetching inserted Results from core data
// Getting products
NSError *error;
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"productId" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor , nil];
[fetchRequest setSortDescriptors:sortDescriptors];
// NSPredicate *predicate = [NSPredicate predicateWithFormat:#"category = %# ",tempCategoryHolder];
// [fetchRequest setPredicate:predicate] ;
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Product"
inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
fetchedObjectsProducts = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];
I would do it like this, assuming tempCategoryHolder holds a categoryId:
NSError *error = nil;
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:#"Product"];
fetchRequest.predicate = [NSPredicate predicateWithFormat:#"category.categoryId = %#", tempCategoryHolder];
fetchRequest.sortDescriptors = #[[NSSortDescriptor sortDescriptorWithKey:#"productId" ascending:YES]];
NSArray *fetchedObjectsProducts = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];
Otherwise update the predicate to refer to category object, or different category attribute.
Currently, I have a table view which is populated by video objects depending on the date they were recorded which was taken by using [nsdate date]; when they were recorded and saved. However, it is possible to record multiple videos in one day. I sort them by the date, and when there is more than one video with the same date, it displays the first one recorded on that date, with the most recent ones following in ascending order according to the most recent. I'm not sure why this happens but would like to check if there are more than one videos with the same date recorded, it organizes them by title. In SQL I could do something like:
ORDER BY DATE_RECORDED, TITLE ASC
Here is what I am currently doing:
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
_managedObjectContext = [appDelegate managedObjectContext];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"whosVideo == %#", _currentPerson];
[request setPredicate:predicate];
NSEntityDescription *eval = [NSEntityDescription entityForName:#"Video" inManagedObjectContext:_managedObjectContext];
[request setEntity:eval];
NSSortDescriptor *sortDescriptor =
[[NSSortDescriptor alloc] initWithKey:#"date_recorded"
ascending:NO
selector:#selector(localizedCaseInsensitiveCompare:)];
NSArray *sortDescriptors = [[NSArray alloc]initWithObjects:sortDescriptor, nil];
[request setSortDescriptors:sortDescriptors];
NSError *error = nil;
NSMutableArray *mutableFetchResults = [[_managedObjectContext executeFetchRequest:request error:&error] mutableCopy];
if (mutableFetchResults == nil){
//handle error
}
[self setVideoArray:mutableFetchResults];
[self.tableView reloadData];
How would I handle adding a second predicate if there is more than one object recorded on the same date?
If you want to handle more than one predicate than you have to use NSCompoundPredicate try like this below:-
NSPredicate *predicate1 = [NSPredicate predicateWithFormat:#"whosVideo == %#", _currentPerson];
NSPredicate *predicate2 = [NSPredicate predicateWithFormat:#"whosVideo == %#", _someOther];
NSArray *subPredicates = [[NSArray alloc] initWithObjects:predicate1, predicate2,nil];
NSPredicate *predicate = [NSCompoundPredicate orPredicateWithSubpredicates:subPredicates];