Давний наблюдатель, спрашивающий впервые.
Я использую Realm Cocoa (от Realm.io) в проекте и изо всех сил пытаюсь выполнить поиск по ПК. Допустим, у меня есть объект с именем RLMFoo
, у которого есть первичный ключ с именем bar
. У меня также есть список ПК, скажем, сохраненный в массиве:
NSArray *primaryKeys = @[@"bar1", @"bar2", @"bar3"]
Есть ли способ получить все объекты класса RLMFoo
из моей области одним запросом?
Я пробовал до сих пор:
- Предикат в формате:
[RLMFoo objectsInRealm:realm withPredicate:[NSPredicate predicateWithFormat:@"bar IN %@", primaryKeys]];
- Царство где:
[RLMFoo objectsInRealm:realm where:@"bar IN %@", strippedIds];
- Предикат с блоком:
.
NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(id
evaluatedObject, NSDictionary *bindings) {
RLMFoo *foo = (RLMFoo *)evaluatedObject;
return [primaryKeys containsObject:foo.bar];
}];
[RLMFoo objectsInRealm:realm withPredicate:predicate];
Но единственное, что я нашел работающим до сих пор, это запрашивать область для каждого значения первичного ключа и агрегировать результаты, что кажется медленным:
NSMutableArray *results = [NSMutableArray new];
for (NSString *primaryKey in primaryKeys) {
RLMFoo *obj = [RLMFoo objectInRealm:realm forPrimaryKey:primaryKey];
if (obj) {
[results addObject:obj];
}
}
Кто-нибудь знает лучший способ сделать это?
========= Объяснение того, почему первые три метода не работают =======
1) Причина, по которой это не работает, кажется очевидной из сообщения об исключении: IN принимает только 2 значения, хотя SQL-версия IN должна принимать столько, сколько необходимо. Как видно из исходного кода RLMQueryUtil.mm
, то же самое относится и к оператору BETWEEN:
if (compp.predicateOperatorType == NSBetweenPredicateOperatorType || compp.predicateOperatorType == NSInPredicateOperatorType) {
// Inserting an array via %@ gives NSConstantValueExpressionType, but
// including it directly gives NSAggregateExpressionType
if (exp1Type != NSKeyPathExpressionType || (exp2Type != NSAggregateExpressionType && exp2Type != NSConstantValueExpressionType)) {
@throw RLMPredicateException(@"Invalid predicate",
@"Predicate with %s operator must compare a KeyPath with an aggregate with two values",
compp.predicateOperatorType == NSBetweenPredicateOperatorType ? "BETWEEN" : "IN");
}
Вот трассировка стека:
*** Terminating app due to uncaught exception 'Invalid predicate', reason: 'Predicate with IN operator must compare a KeyPath with an aggregate with two values'
*** First throw call stack:
(
0 CoreFoundation 0x03334946 __exceptionPreprocess + 182
1 libobjc.A.dylib 0x0292aa97 objc_exception_throw + 44
2 <redacted> 0x00190569 _ZN12_GLOBAL__N_127update_query_with_predicateEP11NSPredicateP9RLMSchemaP15RLMObjectSchemaRN7tightdb5QueryE + 2553
3 <redacted> 0x0018f7ea _Z27RLMUpdateQueryWithPredicatePN7tightdb5QueryEP11NSPredicateP9RLMSchemaP15RLMObjectSchema + 378
4 <redacted> 0x0018b23c _Z13RLMGetObjectsP8RLMRealmP8NSStringP11NSPredicate + 748
5 <redacted> 0x0017d721 +[RLMObject objectsInRealm:withPredicate:] + 161
2) Это очень похоже по причине и трассировке стека:
*** Terminating app due to uncaught exception 'Invalid predicate', reason: 'Predicate with IN operator must compare a KeyPath with an aggregate with two values'
*** First throw call stack:
(
0 CoreFoundation 0x03328946 __exceptionPreprocess + 182
1 libobjc.A.dylib 0x0291ea97 objc_exception_throw + 44
2 <redacted> 0x00184599 _ZN12_GLOBAL__N_127update_query_with_predicateEP11NSPredicateP9RLMSchemaP15RLMObjectSchemaRN7tightdb5QueryE + 2553
3 <redacted> 0x0018381a _Z27RLMUpdateQueryWithPredicatePN7tightdb5QueryEP11NSPredicateP9RLMSchemaP15RLMObjectSchema + 378
4 <redacted> 0x0017f26c _Z13RLMGetObjectsP8RLMRealmP8NSStringP11NSPredicate + 748
5 <redacted> 0x00171751 +[RLMObject objectsInRealm:withPredicate:] + 161
6 <redacted> 0x00171465 +[RLMObject objectsInRealm:where:args:] + 213
7 <redacted> 0x001712f3 +[RLMObject objectsInRealm:where:] + 419
3) Этот, опять же, очень похож. К чему это сводится, так это к отсутствию поддержки со стороны области для полного набора функций NSPredicate.
*** Terminating app due to uncaught exception 'Invalid predicate', reason: 'Only support compound and comparison predicates'
*** First throw call stack:
(
0 CoreFoundation 0x03308946 __exceptionPreprocess + 182
1 libobjc.A.dylib 0x028fea97 objc_exception_throw + 44
2 <redacted> 0x001638bd _ZN12_GLOBAL__N_127update_query_with_predicateEP11NSPredicateP9RLMSchemaP15RLMObjectSchemaRN7tightdb5QueryE + 4397
3 <redacted> 0x0016240a _Z27RLMUpdateQueryWithPredicatePN7tightdb5QueryEP11NSPredicateP9RLMSchemaP15RLMObjectSchema + 378
4 <redacted> 0x0015de5c _Z13RLMGetObjectsP8RLMRealmP8NSStringP11NSPredicate + 748
5 <redacted> 0x00150341 +[RLMObject objectsInRealm:withPredicate:] + 161