Составной запрос CloudKit (запрос с ИЛИ)

Я хотел бы запросить CloudKit, используя ИЛИ с двумя полями. Но я не могу найти способ, как это сделать. Что я сделал:

NSPredicate *predicate1 = [NSPredicate predicateWithFormat:@"(creatorUserRecordID == %@)", userId];
NSPredicate *predicate2 = [NSPredicate predicateWithFormat:@"(toUser == %@)", userId];
NSCompoundPredicate *compPredicate = [NSCompoundPredicate orPredicateWithSubpredicates:@[predicate1, predicate2]];
CKQuery *query = [[CKQuery alloc] initWithRecordType:@"Message" predicate:compPredicate];

Но, к сожалению, CKQuery не поддерживает запрос ИЛИ (как написано в документации). Могу ли я добиться этого эффекта каким-то другим способом?


person Wojtek    schedule 20.06.2015    source источник


Ответы (1)


CKQuery поддерживает AND и NOT, так что вы можете себе представить, что можете использовать простую логическую алгебру для создания запроса, основанного на том факте, что NOT(NOT A AND NOT B) == A OR B. ОДНАКО, в документации конкретно сказано:

"Составной оператор НЕ не поддерживается в следующих случаях:

Вы не можете использовать его для отрицания составного предиката AND».

Таким образом, вы должны запросить каждый из предикатов ORed отдельно, сохранить их каждый как SET, а затем выполнить пересечение двух наборов, чтобы получить окончательный результат.

person harryhorn    schedule 20.06.2015
comment
Я уже пробовал. Когда я использую NOT (creatorUserRecordID != %@ AND toUser != %@), у меня возникает ошибка: Завершение работы приложения из-за необработанного исключения «CKException», причина: «Ожидаемый подпредикат сравнения. С другой стороны, если я попробую то же самое, но НЕ так: (creatorUserRecordID != %@ AND toUser != %@) это сработает - person Wojtek; 21.06.2015
comment
Может быть, есть причина, по которой они не реализовали ИЛИ в CKRecord? Но я не понимаю, почему... - person Wojtek; 21.06.2015
comment
Ты прав. Еще раз взглянув на документацию, в ней конкретно говорится: Составной оператор НЕ не поддерживается в следующих случаях: Вы не можете использовать его для отрицания составного предиката И. Итак, кажется, вам нужно запросить каждый отдельно, а затем в вашем коде использовать SET, чтобы найти пересечение обоих результатов. Обновлен мой ответ, чтобы отразить это. - person harryhorn; 21.06.2015
comment
5 лет спустя до сих пор не вижу ничего подобного. Лучшее, что я сделал, это сделать перекрестную ссылку на мою запись, а затем получить ее, используя равный предикат, который возвращает массив элементов в одном запросе. - person Jakub; 02.01.2020