Join and Group by SQL to NSFetchRequest Statements - ios

I am using core data first time and facing issue in fetching data from two Tables/Entity.
SQL is as below which is working fine:
Select * from ZMESSAGE msg Left Join ZCONTACT c ON c.ZCHANNEL = msg.ZCHANNEL group by msg.ZCHANNEL Order by msg.ZDATE
Can you please suggest, How to write in NSFetchRequest Statement?
My Entity as below:
I have tried some cases and last one is as below:
NSFetchRequest* fetchGroupSummary = [NSFetchRequest fetchRequestWithEntityName:#"Message"];
NSEntityDescription* entity = [NSEntityDescription entityForName:#"Message" inManagedObjectContext:self.managedObjectContext];
NSRelationshipDescription *groupName = [entity.relationshipsByName objectForKey:#"channels"];
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:#"date" ascending:YES];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"channels.channel == channel"];
[fetchGroupSummary setEntity:entity];
[fetchGroupSummary setSortDescriptors:#[sortDescriptor]];
[fetchGroupSummary setPropertiesToFetch:[NSArray arrayWithObjects:groupName, nil]];
[fetchGroupSummary setPropertiesToGroupBy:[NSArray arrayWithObject:groupName]];
[fetchGroupSummary setResultType:NSDictionaryResultType];
[fetchGroupSummary setPredicate:predicate];
NSError* error = nil;
NSArray *results = [self.managedObjectContext executeFetchRequest:fetchGroupSummary error:&error];
return results;
Thanks

Related

How do I query for values grouped by unique values in core data?

Consider the above model with to-many relation.
Let's assume I am querying to get managed-objects where patient first or last name is "xyz" (there are multiple records of "xyz").
How to get a unique "xyz" as dictionary object and repeated "xyz" Managed-objets as objects in that dictionary.
So far I am able to get distinct values and also I am able to get array of managed objects where "xyz" is the predicate string.
But I am unable to think of a way to get array of dictionaries with its objects as managed-objects of duplicate values.
I want to have an array of dictionaries with unique value as dictionary name and objets in dictionary should be managed-objects/dictionaries.
Could somebody please help me with this. I will provide more explanation if any part is not understood.
Thanks
#pragma mark - Search Patients By Patient Name
-(NSArray*)GetBillsForPatientwith:(NSString*)name{
NSMutableArray *AllBillsData = [[NSMutableArray alloc]init];
NSArray *_strings = [self GetSplitStrings:name];
NSManagedObjectContext *context = [CoreDataManager GetCoreDataManager].managedObjectContext;
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:_Claims inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"patient_FirstName" ascending:YES];
NSArray *sortDescriptors = #[sortDescriptor];
[fetchRequest setSortDescriptors:sortDescriptors];
NSMutableArray *subPredicates = [NSMutableArray array];
for (NSString *strings in _strings) {
[subPredicates addObject:
[NSPredicate predicateWithFormat:#"patient_FirstName CONTAINS[cd] %# OR patient_LastName contains[cd] %#",strings,strings]];
}
NSCompoundPredicate *predicate_ = [[NSCompoundPredicate alloc]initWithType:NSOrPredicateType subpredicates:subPredicates];
[fetchRequest setReturnsObjectsAsFaults:NO];
[fetchRequest setPredicate:predicate_];
fetchRequest.returnsDistinctResults = YES;
fetchRequest.resultType = NSDictionaryResultType;
fetchRequest.propertiesToFetch = [NSArray arrayWithObjects:[[entity propertiesByName] objectForKey:#"patient_FirstName"],[[entity propertiesByName] objectForKey:#"patient_LastName"], nil];
//fetchRequest.propertiesToGroupBy = [NSArray arrayWithObjects:[[entity propertiesByName] objectForKey:#"patient_FirstName"],[[entity propertiesByName] objectForKey:#"patient_LastName"], nil];
NSError *error;
NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
if (fetchedObjects == nil) {
// Handle the error.
}
for (NSDictionary *names in fetchedObjects) {
// [AllBillsData addObject:names];
[AllBillsData addObject:[self GetCorrespondingClaimsForNames:names]];
}
return AllBillsData;
}
//Entangled Method
-(NSArray*)GetCorrespondingClaimsForNames:(id)Names{
NSManagedObjectContext *context = [CoreDataManager
GetCoreDataManager].managedObjectContext;
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:_Claims inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"patient_FirstName" ascending:YES];
NSArray *sortDescriptors = #[sortDescriptor];
[fetchRequest setSortDescriptors:sortDescriptors];
NSMutableArray *subPredicates = [NSMutableArray array];
[subPredicates addObject:
[NSPredicate predicateWithFormat:#"patient_FirstName ==[cd] %# AND patient_LastName ==[cd] %#",[Names valueForKey:#"patient_FirstName"],[Names valueForKey:#"patient_LastName"]]];
NSCompoundPredicate *predicate_ = [[NSCompoundPredicate alloc]initWithType:NSOrPredicateType subpredicates:subPredicates];
[fetchRequest setReturnsObjectsAsFaults:NO];
[fetchRequest setPredicate:predicate_];
NSError *error;
NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
if (fetchedObjects == nil) {
// Handle the error.
}
return fetchedObjects;
}

core data :fetching data from entity

i have to use following query for fetching data:
SELECT * FROM t1.guides AS t1 JOIN guide_category_int AS t2 ON t1.id = t2.guide_id WHERE t2.category_id = 'category_id' AND t1.start_date >= 'today()' AND t1.end_date <= 'today()' ORDER BY t1.name ASC
How can I use this in core data?
Your fetch request will be something like this:
NSManagedObjectContext *context = ...
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Guides" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"guide.category_id == %# and start_date >= %# and end_date <= %#", #"category_id", [NSDate date], [NSDate date]]];
[fetchRequest setPredicate:predicate];
NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:#"name" ascending:YES];
[fetchRequest setSortDescriptors:[NSArray arrayWithObject:sort]];
[sort release];
NSError *error;
NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
if ([fetchedObjects count] > 0) {
//...
}
[fetchRequest release];
Also you can enable SQLDebug to see raw sql requests, and play with predicate and sort descriptor as you want. How to enable described there

select one to many relation in core data fetch don't work

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.

NSFetchController and many-to-many in coredata

For better understanding my problem imagine your facebook friends; I have one entity "user" and I use that for displaying relationship between friends;
I don't know how to get friends of concrete user using NSFetchRequest
I have two "to many" relationship(see above) and I try to get friends using NSPredicate, but in the end array is empty.
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = (NSEntityDescription *)[_dbManager userEntity];
[fetchRequest setEntity:entity];
User *userByUid = [_dbManager userByUid:_currentUid];
NSSortDescriptor *sort = [[NSSortDescriptor alloc]
initWithKey:#"sortId" ascending:YES];
[fetchRequest setSortDescriptors:[NSArray arrayWithObject:sort]];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"(friends IN %#)", userByUid];
[fetchRequest setPredicate:predicate];
[fetchRequest setFetchBatchSize:10];
NSArray *array = [_fetchedResultsController.managedObjectContext executeFetchRequest:fetchRequest error:nil];
You have to use the inverse relationship and "ANY":
[NSPredicate predicateWithFormat:#"ANY beFriendsWith == %#", userByUid]

NSFetchRequest, possible to filter by aggregate functions?

I am trying to pull all the Actions which belong to the latest Session.
In SQL this would be a simple JOIN ... WHERE Session.startTime = MAX(Session.startTime), but with Core Data I can't figure out how to do this without resorting to two steps as below. Any ideas?
// Step 1. Get the latest session
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:[NSEntityDescription entityForName:#"Session" inManagedObjectContext:self.managedObjectContext]];
[request setSortDescriptors:[NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:#"startTime" ascending:NO]]];
[request setFetchLimit:1];
Session *lastSession = nil;
NSArray *objects = [self.managedObjectContext executeFetchRequest:request error:NULL];
if ([objects count] > 0)
{
NSLog(#"max: %#", [objects objectAtIndex:0]);
lastSession = [objects objectAtIndex:0];
}
// Step 2. Get that session's actions
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Action" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
NSSortDescriptor *sectionSort = [[NSSortDescriptor alloc] initWithKey:#"session.startTime" ascending:NO selector:nil];
NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:#"startTime" ascending:NO selector:nil];
[fetchRequest setSortDescriptors:[NSArray arrayWithObjects:sectionSort, sort, nil]];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"session.startTime = %#", lastSession.startTime];
//**Can't I do something like this instead?**
//NSPredicate *predicate = [NSPredicate predicateWithFormat:#"session.startTime = session.#max.startTime"];
[fetchRequest setPredicate:predicate];
[fetchRequest setFetchBatchSize:10];
[self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:#"session.startTime" cacheName:#"ActionHistory"];
self.fetchedResultsController.delegate = self;
NSError *error;
if (![self.fetchedResultsController performFetch:&error])
{
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort(); // Fail
}
Edit: I do need to stick with using NSFetchedResultsController due reasons not fully detailed above.
I would advise you to make a relationship beetwen Session and Action.
Then, after you fetch the session you need, you could get all that session's actions as easy ss lastSession.actions.
Edit
Maybe you can do
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"session = %#",lastSession];

Resources