iPhone: CoreData join - iphone

My question similar to question iPhone CoreData join. The difference is that I need to get all LanguageSets from a database for a given category.categoryName. How predicate will looks like ? Thanks...

I assume its the same schema an you are fetching LanguageEntry. You can assign a predicate to the fetch request like
NSPredicate *predicate=[NSPredicate predicateWithFormat:#"category.categoryName==%#",<given name>];
Since you want only the LanguageSet , you should specify so in the fetch request
[request setPropertiesToFetch:[NSArray arrayWithObject:#"languageSet"]];
Don't forget to set resultType as NSDictionaryResultType.

Related

Issue with setting NSSortDescriptor key in NSFetchResultController

With respect to the above relationship diagram, Earlier, I had a too many relationship between Assignment and Question entity and this is broken to fix a question ordering issue.
Now the relationship to Assignment to Question is through a join table AssignmentQuestion.
Idea here was to sort the question based on the questionOrderIndex property of the AssignmentQuestion table.
I am fetching the assignment questions through a NSFetchResultController. I have written a predicate to fetch the questions accordingly. But since I want the questions to be sorted based questionOrderIndex, my sort key for the sort descriptor through question entity is assignmnetQuestion.questionOderIndex.
But with this sort key, I am getting an exception: "Exception = to-many key not allowed here". Upon investigation, I found that it is because of "one to many" relation from Question to AssignmentQuestion table.
My questions are:
1) How to set the sort key for a Sort descriptor based on questionOrderIndex?
2) Do we really need to have a join table here in core data to sort the questions in order?
Predicate to fetch Questions:
NSString *predicateString = [NSString stringWithFormat:#"self.evaluationQuestion.assignmentEvaluation.assignmentId == %#", #"1"];
If you don't need to listen for changes on the questions (external to your view controller), you could fetch the the AssignmentQuestion entities instead, and prefetch the attached questions.
later, in your view controller, instead of using the AssignmentQuestion entities, use their prefetched question relationship
//code not tested
NSFetchRequest* request = [NSFetchRequest fetchRequestWithEntityName:#"AssignmentQuestion"];
[request setPredicate:[NSPredicate predicateWithFormat:#"assignmentEvaluation.assignmentId == %#",assignmentId]];
[request setRelationshipKeyPathsForPrefetching:#[#"question"]];
[request setSortDescriptors:#[[NSSortDescriptor sortDescriptorWithKey:#"questionOrderIndex" ascending:YES]]];
also see here

how to implement that in core data

in SQL we use the following clause
where studentName like '%a' and StudentID = 1
how to do that in objective c and core data using setpredicate for fetchrequest
I have only two inputs part of the name #"a" and the ID #"1"
best regards
Take a look at the Predicate Programming Guide.
I would also like to add the Core Data Programming Guide - Fetching Managed Objects.
it worked with contains[cd] but I want
to know what if I passed the string
empty and want to search by ID only
Normally, you don't use empty strings in a fetch predicate because core data will try to match the empty string. Instead, you should create different fetch request for different circumstances. Fetch request are lightweight objects than can be stored in arrays (or even the data model itself.)
If this case, you would test for an empty string and if true use a fetch predicate that only looks for the StudentID.
In general, try to avoid thinking of Core Data in SQl terms. It's natural but dangerous. Core Data is not SQL. Entities are not tables. Objects are not rows. Columns are not attributes. Core Data is an object graph management system that may or may not persist the object graph and may or may not use SQL far behind the scenes to do so. Trying to think of Core Data in SQL terms will cause you to completely misunderstand Core Data and result in much grief and wasted time.
I agree with TechZen, you should be thinking of core data in terms of objects, as opposed to being sql backed. CD uses SQL as an implementation detail, not necessarily as a defining feature.
This is an example from the developer library
Creating Fetch Request Templates Programmatically
basicly it looks something like this using predicated...
NSManagedObjectModel *model = <#Get a model#>;
NSFetchRequest *requestTemplate = [[NSFetchRequest alloc] init];
NSEntityDescription *publicationEntity =
[[model entitiesByName] objectForKey:#"Publication"];
[requestTemplate setEntity:publicationEntity];
NSPredicate *predicateTemplate = [NSPredicate predicateWithFormat:
#"(mainAuthor.firstName like[cd] $FIRST_NAME) AND \
(mainAuthor.lastName like[cd] $LAST_NAME) AND \
(publicationDate > $DATE)"];
[requestTemplate setPredicate:predicateTemplate];
[model setFetchRequestTemplate:requestTemplate
forName:#"PublicationsForAuthorSinceDate"];
[requestTemplate release];
so by looking at that your probably after something like this
NSPredicate *predicateTemplate = [NSPredicate predicateWithFormat:
#"(mainAuthor.firstName like[cd] $FIRST_NAME) AND \
(mainAuthor.lastName like[cd] $LAST_NAME) AND \
(publicationDate > $DATE)"];
[requestTemplate setPredicate:predicateTemplate];
hope this helps I'm currently setting up core data in my project and have been reading through this stuff all morning.

Core data predicate with group and MAX()

I have an object in core data that has 2 fields: Name and Date. Each time a person checks in it saves their name and the time they did it.
Is there a way to get a list of all unique people with their last check in time using a predicate in core data?
Note: i do know that 2 tables would make it easier.
the sql for this would be
select
clientName
, MAX(ModifiedDate)
from
Client
group by
clientName
Beginning from iOS 5.0 / OS X 10.7 NSFetchRequest class includes the setPropertiesToGroupBy: instance method, which allow to create aggregated requests on persistent storage level.
You would have to set NSDictionaryResultType as the result type, thus telling NSFetchRequest object to return NSDictionary objects with aggregated data instead of managed objects.
Example code for max() requests:
[request setResultType:NSDictionaryResultType];
NSExpression *dateKeyExpression = [NSExpression expressionForKeyPath:#"date"];
NSExpression *maxDateExpression = [NSExpression expressionForFunction:#"max:" arguments:[NSArray arrayWithObject:dateKeyExpression]];
NSExpressionDescription *maxDateED = [[NSExpressionDescription alloc] init];
[maxDateED setExpression:maxDateExpression];
[maxDateED setName:#"maxDate"];
[maxDateED setExpressionResultType:NSDateAttributeType];
NSAttributeDescription *clientName = [[self entityDescription].attributesByName objectForKey:#"clientName"];
[request setPropertiesToFetch:[NSArray arrayWithObjects:clientName, maxDateED, nil]];
[request setPropertiesToGroupBy:[NSArray arrayWithObject:clientName]];
No not easily since Core Data is an object graph first. You could do it by grabbing a distinct set of the names and then querying for the max for each via a sort.
The best answer is to break it into two tables otherwise it is going to be computationally expensive each time you try and resolve this.
OR/M Layer
Don't think of it as an OR/M layer. Core Data is an object graph; full stop.
The fact that it happens to persist to a database structure as one of its persistence options is secondary.
The issue in your question is that you are trying to use an Object Graph as a database. In that situation I get to use a phase that is very frequently attributed to me:
"You're doing it wrong." :)

Retrieve unique results with Core Data, NSPredicate?

I need to be able to do the equivalent of the following SQL using Core Data:
SELECT DISTINCT(foo) FROM bar
Is there a way of doing this with NSPredicate? Or any other way for that matter?
I believe all you need to do is add this to your NSFetchRequest
[request setReturnsDistinctResults:YES];

Unique Values from Core Data

I have a core data-based app that manages records of auto dealerships. Each record stores the dealer's address, which is broken into addressLine1, addressLine2, city, state, and zip components, each stored as a string in the data store.
I would like to present a list of cities with dealerships to the user, so I'm trying to figure out if it is possible to get a list of every unique city name that has been entered into the store. I other words, is it possible to issue some sort of query against all of the dealership records that will return a list of distinct city names?
I would know how to do this easily with a SQL query, but (how) is this done in Core Data?
Thanks very much!
Core Data have the option to get distinct record. The method of getting unique results using NSArray and NSSets are not recommend.
[fetchRequest setResultType:NSDictionaryResultType];
NSDictionary *entityProperties = [entity propertiesByName];
[fetchRequest setPropertiesToFetch:[NSArray arrayWithObject:[entityProperties objectForKey:#"<<yourattrib>"]]];
[fetchRequest setReturnsDistinctResults:YES];
Refer Apple documentation and check the answers for How to fetch distinct values in Core Data?
You're right, there isn't an "easy" way to do this with Core Data, because Core Data is not a database. However, it is possible. Here's the general idea:
Fetch all your Dealer objects via an NSFetchRequest. To simplify the query, you can set the fetch request to only fetch the city attribute.
Execute NSArray * uniqueCities = [fetchedDealers valueForKeyPath:#"#distinctUnionOfObjects.city"];
A quick way to ensure a unique set of things is to use NSSet. Once you have the results for a query on city take your NSArray and do
NSSet* uniqueResults = [NSSet setWithArray:resultsArray];
You can transform the set into another collection class if more convenient or just the object enumerator to do something with all of them. I do not know if this approach or the valueForKeyPath method from Dave DeLong is more efficient.