Нечувствительный к регистру NSP предикат для строк из массива? - PullRequest
8 голосов
/ 07 января 2010

У меня есть ситуация, когда я хочу получить объекты из моего основного хранилища данных по ключу имени пользователя, но я хочу, чтобы сравнение было без учета регистра. Предикат, который у меня есть, таков:

username IN $usernames

Затем я делаю подстановку переменных с массивом строк, которые представляют собой имена пользователей, которые я хочу найти. Это работает, но с учетом регистра. Я хотел бы сделать что-то вроде этого, я думаю:

username IN[c] $usernames

К сожалению, это не похоже на работу. Сравнение строк по-прежнему должно выполняться с учетом регистра. (Я не получаю сообщение об ошибке, что запрос не поддерживается.)

Есть ли другой способ написать этот предикат, чтобы он работал так, как мне нужно, или я просто упускаю что-то очевидное здесь?

Ответы [ 4 ]

11 голосов
/ 07 января 2010

Модификатор case в операторе IN, по-видимому, игнорируется при выполнении выборки из хранилища SQLite. (Вы пропустили тип магазина из вашего вопроса.)

Я бы порекомендовал сообщить об ошибке в документации, чтобы можно было документировать это ограничение / поведение.

Я бы также рекомендовал подать запрос на добавление функции в репортере ошибок, чтобы это можно было рассмотреть для дальнейшей поддержки.

Тем временем вам придется извлечь запрос на выборку из модели данных и построить его программно. Вы можете создать составной предикат ИЛИ предикат, который сопоставляет равенство без учета регистра для каждого из ваших значений (и проверить, соответствует ли он вашим требованиям к производительности.)

Обратите внимание, что если вы поддерживаете цели ОС до 10.6, модификатор case на == не поддерживается, и в этом случае потребуется еще одно альтернативное решение.

1 голос
/ 07 января 2010

Вот еще один обходной путь, но он требует смены MOM.

Сделать имя пользователя полноценной сущностью. Создайте обратную связь между именем пользователя и тем, чем является ваша другая сущность.

Теперь для запроса на выборку установите сущность как «Имя пользователя», затем запустите этот предикат (при условии, что свойство «имя» и свойство «родитель»):

   [NSPredicate predicateWithFormat:"(name like[c] %@) && (parent == %@)", theUserName, theParentObject]

Это может быть излишним, но позволит вам выполнить поиск по желанию.

1 голос
/ 07 января 2010

Вы можете попробовать что-то вроде ANY $usernames LIKE[c] username. Я сделал нечто подобное, где вместо подстановки переменных у меня просто есть ключевой путь, такой как "people.name", и этот предикат работает для меня. Не уверен, что он работает по-другому с переменной там, а не с путем ключа, но стоит попробовать.

0 голосов
/ 13 апреля 2015

Хотя этому вопросу уже несколько лет, я наткнулся на ту же проблему и решил ее так:

NSArray  *values = @[@"FOO", @"bar" ,@"lorem"];
NSString *predicate;

predicate = @"value LIKE[cd] '";
predicate = [predicate stringByAppendingString:
             [values componentsJoinedByString:
              @"' OR  value LIKE[cd] '"]];
predicate = [predicate stringByAppendingString:@"'"];

NSLog(@"%@",  predicate);
// Output:
// value LIKE[cd] 'FOO' OR  value LIKE[cd] 'bar' OR  value LIKE[cd] 'lorem'

Это создает статическое выражение предиката из списка значений. Может быть, это кому-нибудь пригодится.

ОБНОВЛЕНИЕ 2:

На самом деле, похоже, что обновленное решение ниже не работает с sqlite и выдает

'NSInvalidArgumentException',
reason: 'unimplemented SQL generation for predicate : ... (bad LHS)'

Я думаю, что для сравнения массивов / dict / set и IN в левой части оператора разрешены только ключи.

UPDATE:

После некоторого исследования выражений и предикатов я обнаружил еще один подход, который, кажется, работает довольно хорошо:

NSPredicate *predicate =
   [NSPredicate predicateWithFormat:
     @"lowercase(value) IN %@", values];

При этом используется выражение функции lowercase: для получения строчного представления значения. Все, что осталось сделать, - это убедиться, что все записи values строчные, и вы сможете использовать регистрозависимые IN выражения.

...