Shvalb
Shvalb

Reputation: 1933

Core Data - Select distinct

I know there have been several discussions about this but none of them resolved my simple problem.

I have an Entity called Character and inside there are 4 columns: character_id, episode_id, title, desc

there can be several same character_ids values but with different episode_id.

When I perform fetch\select I do it for whole table and wishes to get it distinctly by character_id. so this is what I do:

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:entityName    inManagedObjectContext:moc];
[fetchRequest setEntity:entity];

// Add a sort descriptor. Mandatory.
if(sortDescriptors != nil) {
    [fetchRequest setSortDescriptors:sortDescriptors];
}

fetchRequest.predicate = predicate;

// Required! Unless you set the resultType to NSDictionaryResultType, distinct can't work.
// All objects in the backing store are implicitly distinct, but two dictionaries can be duplicates.
// Since you only want distinct names, only ask for the 'name' property.
fetchRequest.resultType = NSDictionaryResultType;
fetchRequest.propertiesToFetch = [NSArray arrayWithObject:[[entity propertiesByName] objectForKey:@"title"]];
fetchRequest.returnsDistinctResults = YES;


NSArray *fetchResults = [moc executeFetchRequest:fetchRequest error:&error];

The 'fetchResults' array contains 3 out of 10 rows which is the right result!

The problem: None of the object within the array is accessible.

If I try the following:

NSDictionary item1 = [fetchResults objectAtIndex:0];
NSString *title = [item1 objectForKey:@title"];

I get an exception!

What am I doing wrong?? how can I translate back the dictionary into NSManagedObjects??

Thank you!

Upvotes: 0

Views: 1657

Answers (1)

Mundi
Mundi

Reputation: 80273

First, when using Core Data you should not use foreign keys. Rather, it is preferable to use Core Data's relationships and let the framework deal with the ids in an opaque manner. Maybe you are synching with a web service and need to keep track of the ids but your program logic actually should not depend on it.

Second, if you need an object, it is really better to use the NSManagedObjectResultType rather than the NSDictionaryResultType. You can still obtain distinct results. If you are not experiencing performance issues, this is the preferred pattern. The code is also much more readable.

Your data structure would be this, with a many-to-many relationship:

Character <<--->> Episode

All characters of an episode or all episodes with a certain character is simple. These will be "distinct" results dictated by the logic of the data model:

NSArray *allCharactersInEpisode = episode.characters;
NSArray *allEpisodesWithCharacter = character.episodes;

To select all characters of all episodes you just select all characters. Much simpler than a "distinct" query.

Upvotes: 2

Related Questions