Add case insensitive sort option #135

Open
dbowen opened this Issue Jan 21, 2012 · 13 comments

Comments

Projects
None yet
9 participants
@dbowen

dbowen commented Jan 21, 2012

It’d be nice have a case insensitive version of all the fetching functions with a sort option. Currently we have to do this with a predicate from what I’ve seen, but it’d be nice to have this option as I don’t believe its too uncommon.

@ghost

This comment has been minimized.

Show comment
Hide comment
@ghost

ghost Jan 21, 2012

Collaborator

Unless you're exposing predicates to the user, I don't think it's too much to ask that you have the case of your own properties correct in your searches and sorts. Besides, if you made case insensitivity the default, by default all searches and sorts would take longer. The goal is to make coding easier with as little impact on performance as possible.

Saul Mora
Founding Panda
saul@magicalpanda.com

On Jan 20, 2012, at 5:21 PM, dbowen wrote:

It'd be nice have a case insensitive version of all the fetching functions with a sort option. Currently we have to do this with a predicate from what I've seen, but it'd be nice to have this option as I don't believe its too uncommon.


Reply to this email directly or view it on GitHub:
#135

Collaborator

ghost commented Jan 21, 2012

Unless you're exposing predicates to the user, I don't think it's too much to ask that you have the case of your own properties correct in your searches and sorts. Besides, if you made case insensitivity the default, by default all searches and sorts would take longer. The goal is to make coding easier with as little impact on performance as possible.

Saul Mora
Founding Panda
saul@magicalpanda.com

On Jan 20, 2012, at 5:21 PM, dbowen wrote:

It'd be nice have a case insensitive version of all the fetching functions with a sort option. Currently we have to do this with a predicate from what I've seen, but it'd be nice to have this option as I don't believe its too uncommon.


Reply to this email directly or view it on GitHub:
#135

@dbowen

This comment has been minimized.

Show comment
Hide comment
@dbowen

dbowen Jan 21, 2012

I think I miscommunicated, it would be for the ordering of the results, not on the property names themselves. It's more of a suggestion for simplicity rather than necessary, as we can do it with predicates. However, I think we may end up writing it in for ourselves anyway as an option just for simplicity. Is this something you would want a pull request for?

As an example, lets assume we have an inventory system. The user enters various details, mainly product name. Regardless of wether or not the user entered the data as "Pencil" or "pencil", all things starting with the letter 'p' should be in the same area of the tableview based on the product name.

dbowen commented Jan 21, 2012

I think I miscommunicated, it would be for the ordering of the results, not on the property names themselves. It's more of a suggestion for simplicity rather than necessary, as we can do it with predicates. However, I think we may end up writing it in for ourselves anyway as an option just for simplicity. Is this something you would want a pull request for?

As an example, lets assume we have an inventory system. The user enters various details, mainly product name. Regardless of wether or not the user entered the data as "Pencil" or "pencil", all things starting with the letter 'p' should be in the same area of the tableview based on the product name.

@ghost

This comment has been minimized.

Show comment
Hide comment
@ghost

ghost Jan 21, 2012

Collaborator

Right, honestly, I'm seeing the same type of sorting issue myself in an app I'm writing. I haven't come up with something that allows case insensitive sorting yet, but if you have something that can work at the database level (because it's faster), I'm open to adding it....

Saul Mora
Founding Panda
saul@magicalpanda.com

On Jan 20, 2012, at 5:51 PM, dbowen wrote:

I think I miscommunicated, it would be for the ordering of the results, not on the property names themselves. It's more of a suggestion, I think we may end up writing it in for ourselves anyway as an option just for simplicity.

As an example, lets assume we have an inventory system. The user enters various details, mainly product name. Regardless of wether or not the user entered the data as "Pencil" or "pencil", all things starting with the letter 'p' should be in the same area of the tableview based on the product name.


Reply to this email directly or view it on GitHub:
#135 (comment)

Collaborator

ghost commented Jan 21, 2012

Right, honestly, I'm seeing the same type of sorting issue myself in an app I'm writing. I haven't come up with something that allows case insensitive sorting yet, but if you have something that can work at the database level (because it's faster), I'm open to adding it....

Saul Mora
Founding Panda
saul@magicalpanda.com

On Jan 20, 2012, at 5:51 PM, dbowen wrote:

I think I miscommunicated, it would be for the ordering of the results, not on the property names themselves. It's more of a suggestion, I think we may end up writing it in for ourselves anyway as an option just for simplicity.

As an example, lets assume we have an inventory system. The user enters various details, mainly product name. Regardless of wether or not the user entered the data as "Pencil" or "pencil", all things starting with the letter 'p' should be in the same area of the tableview based on the product name.


Reply to this email directly or view it on GitHub:
#135 (comment)

@runmad

This comment has been minimized.

Show comment
Hide comment
@runmad

runmad Jul 6, 2012

I ran into the issue today too. I have a lists of contacts that are pulled from LinkedIn. Out of about 130 contacts, 2 people have written their first and last name in lowercase.

I use:
self.fetchedResultsController = [Contact fetchAllSortedBy:@"firstName" ascending:YES withPredicate:nil groupBy:@"firstName" delegate:self];

And this gives me a list of my contacts sorted by first name, but divides the list up into two, the longer one which has contacts that use uppercase letter for their first name and then at the bottom, the two contacts that have used lower case for their names at the bottom (sorted alphabetically by first name).

runmad commented Jul 6, 2012

I ran into the issue today too. I have a lists of contacts that are pulled from LinkedIn. Out of about 130 contacts, 2 people have written their first and last name in lowercase.

I use:
self.fetchedResultsController = [Contact fetchAllSortedBy:@"firstName" ascending:YES withPredicate:nil groupBy:@"firstName" delegate:self];

And this gives me a list of my contacts sorted by first name, but divides the list up into two, the longer one which has contacts that use uppercase letter for their first name and then at the bottom, the two contacts that have used lower case for their names at the bottom (sorted alphabetically by first name).

@dbowen

This comment has been minimized.

Show comment
Hide comment
@dbowen

dbowen Jul 6, 2012

I asked Apple about this at WWDC, and their recommended solution is to create a normalized attribute to sort on. Not exactly ideal, but it works for now.

In your case I would add the attribute normalizedFirstName, then override the setter for firstName to also set normalizedFirstName as [firstName lowercaseString].

dbowen commented Jul 6, 2012

I asked Apple about this at WWDC, and their recommended solution is to create a normalized attribute to sort on. Not exactly ideal, but it works for now.

In your case I would add the attribute normalizedFirstName, then override the setter for firstName to also set normalizedFirstName as [firstName lowercaseString].

@runmad

This comment has been minimized.

Show comment
Hide comment
@runmad

runmad Jul 6, 2012

Thanks for the follow-up. Strange case, I can't imagine having to sort like this at all, but maybe I am biased due to my use-case.

runmad commented Jul 6, 2012

Thanks for the follow-up. Strange case, I can't imagine having to sort like this at all, but maybe I am biased due to my use-case.

@mbigatti

This comment has been minimized.

Show comment
Hide comment
@mbigatti

mbigatti Jun 22, 2013

Hi. I ran into the same issue. I have a simple lookup table of names that I'd like to order without considering the case. I could follow Apple suggestion and duplicate the name field to store the normalized version, but it seems a waste of space and add complexity to the model. I'm not so happy with it.

How about a solution like this one: RestKit/RestKit#702

Regards,
MB

PS: thanks, MR is awesome

Hi. I ran into the same issue. I have a simple lookup table of names that I'd like to order without considering the case. I could follow Apple suggestion and duplicate the name field to store the normalized version, but it seems a waste of space and add complexity to the model. I'm not so happy with it.

How about a solution like this one: RestKit/RestKit#702

Regards,
MB

PS: thanks, MR is awesome

@casademora

This comment has been minimized.

Show comment
Hide comment
@casademora

casademora Jun 22, 2013

Member

I don't think that is wasteful. You can manage the denormalized data easily with Core Data using the awakeFromInsert and willSave methods. And if it lets you search your data faster, then it's the tradeoff you'll need to get the job done.

The solution you pointed to has a different tradeoff. Since it's using a property on the object to do the grouping, it's all done in memory, in "Object Space" and not in the sqlite database. This is going to be slower overall given all the objects that could be grouped at any one fetch. Try denormalizing your data. It's worked for me in the past, and it is less wasteful of user space than you may realize.

On Jun 22, 2013, at 1:00 PM, mbigatti notifications@github.com wrote:

Hi. I ran into the same issue. I have a simple lookup table of names that I'd like to order without considering the case. I could follow Apple suggestion and duplicate the name field to store the normalized version, but it seems a waste of space and add complexity to the model. I'm not so happy with it.

How about a solution like this one: RestKit/RestKit#702

Regards,
MB

PS: thanks, MR is awesome


Reply to this email directly or view it on GitHub.

Member

casademora commented Jun 22, 2013

I don't think that is wasteful. You can manage the denormalized data easily with Core Data using the awakeFromInsert and willSave methods. And if it lets you search your data faster, then it's the tradeoff you'll need to get the job done.

The solution you pointed to has a different tradeoff. Since it's using a property on the object to do the grouping, it's all done in memory, in "Object Space" and not in the sqlite database. This is going to be slower overall given all the objects that could be grouped at any one fetch. Try denormalizing your data. It's worked for me in the past, and it is less wasteful of user space than you may realize.

On Jun 22, 2013, at 1:00 PM, mbigatti notifications@github.com wrote:

Hi. I ran into the same issue. I have a simple lookup table of names that I'd like to order without considering the case. I could follow Apple suggestion and duplicate the name field to store the normalized version, but it seems a waste of space and add complexity to the model. I'm not so happy with it.

How about a solution like this one: RestKit/RestKit#702

Regards,
MB

PS: thanks, MR is awesome


Reply to this email directly or view it on GitHub.

@ethanparker

This comment has been minimized.

Show comment
Hide comment
@ethanparker

ethanparker Mar 7, 2014

I ran into the same issue. MR_finadAllSortedByCaseinsensitive would be great.

I ran into the same issue. MR_finadAllSortedByCaseinsensitive would be great.

@mohith

This comment has been minimized.

Show comment
Hide comment
@mohith

mohith Apr 6, 2014

This might be against software engineering concepts and mess up performance

But to get things done.

I am directly accessing
(NSFetchedResultsController *) MR_fetchController:(NSFetchRequest *)request delegate:(id<NSFetchedResultsControllerDelegate>)delegate useFileCache:(BOOL)useFileCache groupedBy:(NSString *)groupKeyPath inContext:(NSManagedObjectContext *)context;
from category method in NSManagedObject (MagicalFinders_CustomRequest)

and

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"%@ IN planets.galaxy.ID", self.galaxy.ID];
NSFetchRequest *request = [Planets MR_requestAllSortedBy:nil
                                                ascending:NO
                                            withPredicate:predicate
                                                inContext:[NSManagedObjectContext MR_contextForCurrentThread]];
    NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES selector:@selector(localizedCaseInsensitiveCompare:)];
    request.sortDescriptors = [NSArray arrayWithObject:sort];
self.planetsFetchController = [Planets MR_fetchAllWithRequest:request
                            groupBy:nil
                           delegate:self];

cc @ethanparker

mohith commented Apr 6, 2014

This might be against software engineering concepts and mess up performance

But to get things done.

I am directly accessing
(NSFetchedResultsController *) MR_fetchController:(NSFetchRequest *)request delegate:(id<NSFetchedResultsControllerDelegate>)delegate useFileCache:(BOOL)useFileCache groupedBy:(NSString *)groupKeyPath inContext:(NSManagedObjectContext *)context;
from category method in NSManagedObject (MagicalFinders_CustomRequest)

and

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"%@ IN planets.galaxy.ID", self.galaxy.ID];
NSFetchRequest *request = [Planets MR_requestAllSortedBy:nil
                                                ascending:NO
                                            withPredicate:predicate
                                                inContext:[NSManagedObjectContext MR_contextForCurrentThread]];
    NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES selector:@selector(localizedCaseInsensitiveCompare:)];
    request.sortDescriptors = [NSArray arrayWithObject:sort];
self.planetsFetchController = [Planets MR_fetchAllWithRequest:request
                            groupBy:nil
                           delegate:self];

cc @ethanparker

@tonyarnold

This comment has been minimized.

Show comment
Hide comment
@tonyarnold

tonyarnold Apr 8, 2014

Contributor

@mohith that's just fine, and exactly what I would have done.

Assuming it works. Keep in mind that the block-based sort descriptors won't work against a SQLite store — I'm unsure of whether the same is true of the selector-based sort descriptors such as the one you've provided here.

Does it work, and are you using a SQLite based persistent store?

Contributor

tonyarnold commented Apr 8, 2014

@mohith that's just fine, and exactly what I would have done.

Assuming it works. Keep in mind that the block-based sort descriptors won't work against a SQLite store — I'm unsure of whether the same is true of the selector-based sort descriptors such as the one you've provided here.

Does it work, and are you using a SQLite based persistent store?

@mohith

This comment has been minimized.

Show comment
Hide comment
@mohith

mohith May 22, 2014

@tonyarnold Yep it worked.I am using SQLite based persistent store (NSSQLiteStoreType)

mohith commented May 22, 2014

@tonyarnold Yep it worked.I am using SQLite based persistent store (NSSQLiteStoreType)

@naqi naqi referenced this issue in naqi/MagicalRecord Feb 10, 2015

Merged

Allow for case insensitive search #1

@andreyslyusar

This comment has been minimized.

Show comment
Hide comment
@andreyslyusar

andreyslyusar Apr 20, 2015

Merge from @naqi could be the reason of crash:

-[__NSDate localizedCaseInsensitiveCompare:]: unrecognized selector sent to instance 0x17000bc50

I think better to introduce new MR_fetchAll... with NSSortDescriptor as parameter.

Merge from @naqi could be the reason of crash:

-[__NSDate localizedCaseInsensitiveCompare:]: unrecognized selector sent to instance 0x17000bc50

I think better to introduce new MR_fetchAll... with NSSortDescriptor as parameter.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment