CoreData get distinct values of Attribute

前端 未结 4 2241
轻奢々
轻奢々 2020-12-02 08:06

I\'m trying to setup my NSFetchRequest to core data to retrieve the unique values for a specific attribute in an entity. i.e.

an entity with the follow

相关标签:
4条回答
  • 2020-12-02 08:23

    You're trying to use Core Data like a procedural data base instead of as an object graph manager as the API intended, so you won't find an easy way to do this.

    There isn't a straight forward way to do this in Core Data because Core Data is concerned with objects instead of values. Since managed objects are guaranteed to be unique, Core Data doesn't much care about each object's values or whether they are duplicates or some other object's values.

    To find the unique values:

    1. Perform a fetch by specific value. That will give you an array of dictionaries with a key name and a value of the name string itself.
    2. On the returned array in (1) use a set collection operator to return a set of unique values.

    So, something like:

    NSSet *uniqueNames=[fetchedNameDicts valueForKeyPath:@"@distinctUnionOfSets.name"];
    

    ... which will return a set of NSString objects all with a unique value.

    0 讨论(0)
  • 2020-12-02 08:28

    Give a look at Fetching Specific Property Values, it's not necessary to use a Set to get distinct values.

    0 讨论(0)
  • 2020-12-02 08:29

    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);
    
    0 讨论(0)
  • 2020-12-02 08:41

    This is a simple approach in Swift 5.x:

    // 1. Set the column name you want distinct values for
    let column = "name"
    
    // 2. Get the NSManagedObjectContext, for example:
    let moc = persistentContainer.viewContext
    
    // 3. Create the request for your entity
    let request = NSFetchRequest<NSFetchRequestResult>(entityName: "User")
    
    // 4. Use the only result type allowed for getting distinct values
    request.resultType = .dictionaryResultType
    
    // 5. Set that you want distinct results
    request.returnsDistinctResults = true
    
    // 6. Set the column you want to fetch
    request.propertiesToFetch = [column]
    
    // 7. Execute the request. You'll get an array of dictionaries with the column
    // as the name and the distinct value as the value
    if let res = try? moc.fetch(request) as? [[String: String]] {
        print("res: \(res)")
    
        // 8. Extract the distinct values
        let distinctValues = res.compactMap { $0[column] }
    }
    
    0 讨论(0)
提交回复
热议问题