Coredata Get Distinct Values of Attribute

CoreData get distinct values of Attribute

You should use the backing store to help you get distinct records.

If you want to get an array with just John, Betty, Edward here's how you do it:

NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"MyEntity"];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"MyEntity" inManagedObjectContext:self.managedObjectContext];

// 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:@"name"]];
fetchRequest.returnsDistinctResults = YES;

// Now it should yield an NSArray of distinct values in dictionaries.
NSArray *dictionaries = [self.managedObjectContext executeFetchRequest:fetchRequest error:nil];
NSLog (@"names: %@",dictionaries);

Distinct value from core data swift

If you want distinct results, you need to set the fetch request's result type to NSFetchRequestResultType.dictionaryResultType. You can't fetch managed objects and get distinct results, since there might be more than one managed object with the same value.

That would look something like

let fetchRequest: NSFetchRequest<NSDictionary> = NSFetchRequest(entityName: "Journal")
fetchRequest.propertiesToFetch = ["dateAsNumber"]
fetchRequest.returnsDistinctResults = true
fetchRequest.resultType = .dictionaryResultType

The result will be an array of dictionaries. Each will have one key per entry in propertiesToFetch (just one in this case).

If you use propertiesToFetch without dictionaryResultType, you affect how faulting works but not the contents of the result. Using returnsDistinctResults only works if you also use propertiesToFetch, so it's also affected by whether you use dictionaryResultType.

How to fetch distinct values in Core Data?

requestedValue is nothing and is obviously not being used (perhaps it was part of some other example that got cut&paste into this example code--who knows). You can just ignore it.

The keys for the dictionary are the same as the attributes you fetched and are defined in your model. So, for example, if you had a person entity with three attributes defined, name, age, phoneNumber, and you requested only name, that would be the only keys with data in your dictionaries. So:

[request setEntity:entity]; 
[request setResultType:NSDictionaryResultType];
[request setReturnsDistinctResults:YES];
[request setPropertiesToFetch:[NSArray arrayWithObject:@"name"]];

// Execute the fetch
NSError *error;
NSArray *objects = [managedObjectContext executeFetchRequest:request error:&error];
if (objects == nil) {
abort();
}
for( NSDictionary* obj in objects ) {
NSLog(@"Person: %@", [obj objectForKey:@"name"]);
}
// ...

So, if you have 5 people in your data store named Bob, Sally, Joe, Freida and Sue, you would see those names print out. If you want to use any of the other attributes (like their age), you would have to add that to the array you set in setPropertiesToFetch:.

In most cases, it is probably best to simply retrieve the managed object, however. The object will be faulted so you won't even bring attributes into memory unless you actually access them. Plus, if you want to make changes to the objects, you could and persist them to the store (with managed objects).

Core Data fetch entities with only unique attributes

You can both propertiesToFetch and returnsDistinctResults properties of NSFetchRequest to get distinct result of ages across all entities.

https://developer.apple.com/library/mac/documentation/Cocoa/Reference/CoreDataFramework/Classes/NSFetchRequest_Class/#//apple_ref/occ/instp/NSFetchRequest/propertiesToFetch

let fetchRequest = NSFetchRequest(entityName: "Person")
fetchRequest.resultType = .DictionaryResultType
fetchRequest.propertiesToFetch = ["age"]
fetchRequest.returnsDistinctResults = true
let result = try! managedObjectContext.executeFetchRequest(fetchRequest)

Swift Core Data - Request with distinct results

You need to set

request.resultType = NSFetchRequestResultType.DictionaryResultType

It returns dictionaries, but the distinct filter should work.

If you do not want to go down that route, filter in memory (also recommended). Do a normal fetch and then

let distinct = NSSet(array: results.valueForKeyPath("docID") as [String])

With Swift 2.0 I prefer

let distinct = NSSet(array: results.map { $0.docID })

Objective-c. Fetching distinct values of attribute from core data

You can use the following fetch request:

// Fetch request for your entity:
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Entity"];
[request setResultType:NSDictionaryResultType];

// Restrict result to "level == 5":
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"level == %d", 5];
[request setPredicate:predicate];

// Expression description for "@sum.value":
NSExpression *sumExpression = [NSExpression expressionForKeyPath:@"@sum.value"];
NSExpressionDescription *expressionDescription = [[NSExpressionDescription alloc] init];
[expressionDescription setName:@"sumValue"];
[expressionDescription setExpression:sumExpression];
[expressionDescription setExpressionResultType:NSInteger32AttributeType];
[request setPropertiesToFetch:@[expressionDescription]];

NSArray *result = [context executeFetchRequest:request error:&error];

The result for your data is


(
{
sumValue = 94;
}
)

i.e. an array containing one dictionary with the sum of values with level=5.

CoreData getting objects based on a distinct property

You could use propertiesToGroupBy like so:

NSFetchRequest *fr = [NSFetchRequest fetchRequestWithEntityName:@"Article"];
fr.propertiesToGroupBy = @[@"text_hash"];
fr.resultType = NSDictionaryResultType;
NSArray *articles = [ctx executeFetchRequest:fr error:nil];

Core Data unique attributes

I've decided to use the validate<key>:error: method to check if there is already a Managed Object with the specific value of <key>. An error is raised if this is the case.

For example:

- (BOOL)validateMyAttribute:(id *)value error:(NSError **)error {
// Return NO if there is already an object with a myAtribute of value
}

Thanks to Martin Cote for his input.



Related Topics



Leave a reply



Submit