В Руководстве по программированию основных данных написано
Есть некоторые взаимодействия между извлечением и типом магазина. В хранилищах XML, двоичных данных и в памяти оценка дескрипторов предикатов и сортировки выполняется в Objective-C с доступом ко всем функциям Cocoa, включая методы сравнения на NSString. Хранилище SQL, с другой стороны, компилирует предикаты и сортирует дескрипторы в SQL и оценивает результат в самой базе данных.
Далее описываются некоторые другие ограничения использования NSPredicate с NSSQLiteStoreType, но использование здесь «ALL» является (недокументированным) ограничением, связанным с тем, как запрос на выборку выдает SQL.
Под капотом CoreData генерирует три таблицы для вашей схемы:
- таблица для контактов
- стол для группы
- таблица соединений, которая их связывает
И когда вы вызываете myGroup.contacts, запускается что-то вроде этого:
select * from Group join JOIN_TABLE on Group.pk == JOIN_TABLE.group_pk join Contact on JOIN_TABLE.contact_pk == Contact.pk where Group.pk == 12
За одним точечным символом происходит много всего!
В любом случае, чтобы действительно выполнить ваш запрос, вам нужно что-то вроде этого. Я проверил это на реальной базе данных SQLite CD, поэтому имена таблиц выглядят странно, но все равно должно быть понятным:
select ZGROUP.Z_PK as outer_pk from ZGROUP where "myUID" not in
(select ZCONTACT.ZUID as contact_uid from ZGROUP join Z_1GROUPS on Z_1GROUPS.Z_2GROUPS == ZGROUP.Z_PK join ZCONTACT on Z_1GROUPS.Z_1CONTACTS == ZCONTACT.Z_PK where ZGROUP.Z_PK == outer_pk)
Я не эксперт по SQL, но мои наблюдения состоят, во-первых, в том, что этот запрос будет медленным, и, во-вторых, в том, что он от далекого предиката NSP, с которого мы начали, довольно далек Таким образом, только благодаря огромным усилиям CD сможет выполнить запрос SQL для того, что вы хотите сделать, и запрос, который он придет, будет не намного лучше, чем наивная реализация в ObjC.
Как бы то ни было, разработчик Apple говорит здесь , что ALL не поддерживается в SQLite, а документация об обратном неверна. Эта документация все еще там в 2013 году, так что, похоже, никто ничего с этим не сделал.
Во всяком случае, то, что вы должны сделать, это что-то вроде этого:
NSFetchRequest *fetchRequest = ...
NSArray *result = [moc executeFetchRequest:fetchRequest error:&err];
result = [result filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"ALL contacts.uid != %@", contactUId]];
Это позволит оценить предикат в программном обеспечении.