Realm Cocoa:通过PK找到多个对象 [英] Realm Cocoa: finding multiple objects by PKs

查看:167
本文介绍了Realm Cocoa:通过PK找到多个对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

长时间潜伏,第一次提问。

Long time lurker, first time asker.

我正在项目中使用Realm Cocoa(来自Realm.io)并且正在努力通过PK进行搜索。
假设我有一个名为 RLMFoo 的实体,它有一个名为 bar 的主键。我也有一个PK列表,假设存储在一个数组中:

I'm using Realm Cocoa (from Realm.io) in a project and am struggling to perform searches by PKs. Let's say I have an entity called RLMFoo which has a primary key called bar. I also have a list of PKs, let's say stored in an array:

NSArray * primaryKeys = @ [@bar1,@bar2 ,@bar3]

有没有办法检索类 RLMFoo的所有实体来自我的领域一个查询?

Is there any way to retrieve all entities of class RLMFoo from my realm in one single query?

我到目前为止尝试过:


  1. 谓词格式: [RLMFoo objectsInRealm:realm withPredicate:[NSPredicate predicateWithFormat:@bar IN%@,primaryKeys]];

  2. Realm的位置: [RLMFoo objectsInRealm:realm where:@bar IN%@,strippedIds];

  3. 谓词与块:

NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(id
evaluatedObject, NSDictionary *bindings) {
                    RLMFoo *foo = (RLMFoo *)evaluatedObject;
                    return [primaryKeys containsObject:foo.bar];
                }];
        [RLMFoo objectsInRealm:realm withPredicate:predicate];

但到目前为止我发现的唯一工作就是查询每个领域主键值并聚合结果,这似乎很慢:

But the only thing that I've found to work so far, is to query the realm for each primary key value and aggregate the results, which seems slow:

NSMutableArray *results = [NSMutableArray new];
for (NSString *primaryKey in primaryKeys) {
    RLMFoo *obj = [RLMFoo objectInRealm:realm forPrimaryKey:primaryKey];
    if (obj) {
        [results addObject:obj];
    }
}

有谁知道更好的方法吗?

Does anyone know of a better way to do it?

=========解释为什么前三种方法不起作用=======

========= Explaining why the first three methods don't work =======

1)从异常消息中可以看出这个不起作用的原因:IN只需要2个值,尽管IN的SQL版本应该尽可能多地使用。正如我们从 RLMQueryUtil.mm 的源代码中看到的那样,这同样适用于BETWEEN运算符:

1) The reason why this doesn't work seems apparent from the exception message: IN only takes 2 values, although the SQL version of IN should take as many as necessary. As we can see from the source code of RLMQueryUtil.mm, the same applies to the BETWEEN operator:

        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)这在理由和堆栈跟踪中非常相似:

2) This is very similar in reason and stack trace:

*** 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的完整功能集缺乏对领域的支持。

3) This one is, again, very similar. What it boils down to is lack of support from realm for the full feature set of 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


推荐答案

在你的帮助下,我找到了这种行为的原因。
我的真实代码更贴近:

With your help, I was able to find the reason for this behaviour. My real code was something closer to:

  NSArray *primaryKeys = @[ @"bar1", @"bar2", @"bar3" ];

  NSString *primaryKeyName = @"bar";
  RLMResults *results =
      [RLMFoo objectsInRealm:self.realm
               withPredicate:[NSPredicate predicateWithFormat:@"%@ IN %@",
                                                              primaryKeyName,
                                                              primaryKeys]];

这是一种方法,PK和PK名称是方法调用的参数。从理论上讲,这将允许我的类用任何PK名称检索任何对象。
结果我的错误在于假设predicateWithFormat会在这种情况下以与stringWithFormat类似的方式工作,并正确地将PK名称替换为第一个参数,并将PK数组作为第二个参数。然而,解决方案结果是首先组装格式字符串,然后是谓词:

Which was in a method and the PKs and the PK name were parameters to the method call. In theory this would allow my class to retrieve whatever objects with whatever PK name. Turns out my mistake is in assuming predicateWithFormat would, in this case, work in a similar way to stringWithFormat and properly replace the PK name as the first argument and take the PK array as the second one. However the solution turned out to be first assembling the format string, and then the predicate:

  RLMResults *results = [RLMFoo
      objectsInRealm:self.realm
       withPredicate:[NSPredicate
                         predicateWithFormat:
                             [NSString stringWithFormat:@"%@ IN %%@", primaryKeyName],
                             primaryKeys]];

感谢Yoshyosh的时间。

Thanks Yoshyosh for your time.

这篇关于Realm Cocoa:通过PK找到多个对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆