【问题标题】:Core Data: Query objectIDs in a predicate?核心数据:在谓词中查询 objectID?
【发布时间】:2010-10-30 19:02:09
【问题描述】:

我正在使用获取请求和谓词从 Core Data 持久存储中获取一组对象。我当前的谓词只是检查一个属性是否 >= 某个值。这一切都很好,除了我想最终排除当前保存在数组中的任何对象。

我基本上需要能够排除一组对象,我认为我能做到这一点的唯一方法是能够从我的托管对象数组中获取objectID 的列表,并在我的谓词以确保返回的任何对象都不具有相同的objectID。即@"ANY records.objectID NOT IN %@", arrayOfObjectID.

我该怎么做?

【问题讨论】:

    标签: core-data predicate fetch


    【解决方案1】:

    像这样的谓词

    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"NOT (self IN %@)", arrayOfExcludedObjects];
    

    获取请求的实体是数组中对象的实体,应该做你想做的事。当然,这可以与单个谓词中的其他子句组合用于获取请求。

    一般来说,对象比较(例如 self == %@self IN %@)在 Core Data 查询中比较 objectID。参数可以是一个 NSManagedObject 实例一个NSMangedObjectID 实例。所以上面的谓词格式可以用arrayOfExcludedObjects[arrayOfExcludedObjects valueForKey:@"objectID"]作为参数。

    【讨论】:

    • 感谢您的帮助。我尝试使用 [NSPredicate predicateWithFormat:@"self NOT IN %@", myArrayOfManagedObjects] 但在运行时我不断收到“无法解析格式字符串“self NOT IN %@”错误。有什么想法吗?
    • 对不起.. 我发帖前没有测试是我的错误。我已经更正了我的答案(使用“NOT (self IN %@)”而不是“self NOT IN %@”)。
    • 这对我来说效果很好。我用它来过滤使用 SQL 不支持的复杂逻辑。但是 predicateWithBlock 在 SQL 上不起作用(出于合理的原因)。
    【解决方案2】:

    虽然@BarryWark 的回答在处理 fetch 请求时是正确的,但我想向那些尝试将此规则应用于过滤 Core Data 对多关系的人们写一个警告。

    简而言之:如果在过滤多对关系时使用谓词并且 IN 查询的对象数组是 objectID 数组 - 那么您应该在查询字符串中使用 self.objectID,例如

    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(self.objectID IN %@)", arrayOfObjectIDs];
    

    因为在过滤多对关系的情况下仅使用(self IN %@) 会导致不正确的结果 - 它只是一个评估谓词的 NSArray,它对 Core Data 的 NSManagedObjectID 东西一无所知。

    我制作了特殊的测试代码来展示这一点。对不起这么多台词,但值得。有两个实体:User 和 Post,并且 User 有一个名为“posts”的对多关系。

    User *user = [NSEntityDescription insertNewObjectForEntityForName:NSStringFromClass([User class]) inManagedObjectContext:managedObjectContext()];
    
    Post *post = [NSEntityDescription insertNewObjectForEntityForName:NSStringFromClass([Post class]) inManagedObjectContext:managedObjectContext()];
    
    [user addPostsObject:post];
    
    [managedObjectContext() save:nil];
    
    // 1. Both filtered relationship array and fetch result are correct!
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(self IN %@)", @[ post ]];
    
    NSSet *filteredRelationship = [user.posts filteredSetUsingPredicate:predicate];
    
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"Post"];
    NSArray *fetchResult = [managedObjectContext() executeFetchRequest:fetchRequest error:nil];
    
    NSLog(@"\n\n\nPredicate: %@", predicate);
    NSLog(@"filteredRelationship: %@", filteredRelationship);
    NSLog(@"fetchResult: %@", fetchResult);
    
    // 2. Filtered relationship array is empty (wrong), fetch result is correct, !
    predicate = [NSPredicate predicateWithFormat:@"(self IN %@)", @[ post.objectID ]];
    
    filteredRelationship = [user.posts filteredSetUsingPredicate:predicate];
    
    fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"Post"];
    fetchResult = [managedObjectContext() executeFetchRequest:fetchRequest error:nil];
    
    NSLog(@"\n\n\nPredicate: %@", predicate);
    NSLog(@"filteredRelationship: %@", filteredRelationship);
    NSLog(@"fetchResult: %@", fetchResult);
    
    // 3. Filtered relationship array is empty (wrong), fetch result is correct
    predicate = [NSPredicate predicateWithFormat:@"(self.objectID IN %@)", @[ post ]];
    
    filteredRelationship = [user.posts filteredSetUsingPredicate:predicate];
    
    fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"Post"];
    fetchResult = [managedObjectContext() executeFetchRequest:fetchRequest error:nil];
    
    NSLog(@"\n\n\nPredicate: %@", predicate);
    NSLog(@"filteredRelationship: %@", filteredRelationship);
    NSLog(@"fetchResult: %@", fetchResult);
    
    // 4. Filtered relationship array is correct, fetch result is correct
    predicate = [NSPredicate predicateWithFormat:@"(self.objectID IN %@)", @[ post.objectID ]];
    
    filteredRelationship = [user.posts filteredSetUsingPredicate:predicate];
    
    fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"Post"];
    fetchResult = [managedObjectContext() executeFetchRequest:fetchRequest error:nil];
    
    NSLog(@"\n\n\nPredicate: %@", predicate);
    NSLog(@"filteredRelationship: %@", filteredRelationship);
    NSLog(@"fetchResult: %@", fetchResult);
    

    TLDR 输出

    <redacted> Predicate: SELF IN {<Post: 0x2a04f10> (entity: Post; id: 0x2a56c40 <x-coredata://9D07BF41-2DC0-42C1-9DD8-6082A00E7BEB/Post/p1> ; data: { content = nil; title = nil; user = "0x2af2a20 <x-coredata://9D07BF41-2DC0-42C1-9DD8-6082A00E7BEB/User/p1>"; })}
    
    <redacted> filteredRelationship: {(<Post: 0x2a04f10> (entity: Post; id: 0x2a56c40 <x-coredata://9D07BF41-2DC0-42C1-9DD8-6082A00E7BEB/Post/p1> ; data: { content = nil; title = nil; user = "0x2af2a20 <x-coredata://9D07BF41-2DC0-42C1-9DD8-6082A00E7BEB/User/p1>"; }) )}
    
    <redacted> fetchResult: ("<Post: 0x2a04f10> (entity: Post; id: 0x2a56c40 <x-coredata://9D07BF41-2DC0-42C1-9DD8-6082A00E7BEB/Post/p1> ; data: {\n    content = nil;\n    title = nil;\n    user = \"0x2af2a20 <x-coredata://9D07BF41-2DC0-42C1-9DD8-6082A00E7BEB/User/p1>\";\n})")
    
    <redacted> Predicate: SELF IN {0x2a56c40 <x-coredata://9D07BF41-2DC0-42C1-9DD8-6082A00E7BEB/Post/p1>}
    
    <redacted> filteredRelationship: {()}
    
    <redacted> fetchResult: ("<Post: 0x2a04f10> (entity: Post; id: 0x2a56c40 <x-coredata://9D07BF41-2DC0-42C1-9DD8-6082A00E7BEB/Post/p1> ; data: {\n    content = nil;\n    title = nil;\n    user = \"0x2af2a20 <x-coredata://9D07BF41-2DC0-42C1-9DD8-6082A00E7BEB/User/p1>\";\n})")
    
    <redacted> Predicate: objectID IN {<Post: 0x2a04f10> (entity: Post; id: 0x2a56c40 <x-coredata://9D07BF41-2DC0-42C1-9DD8-6082A00E7BEB/Post/p1> ; data: { content = nil; title = nil; user = "0x2af2a20 <x-coredata://9D07BF41-2DC0-42C1-9DD8-6082A00E7BEB/User/p1>";})}
    
    <redacted> filteredRelationship: {()}
    
    <redacted> fetchResult: ("<Post: 0x2a04f10> (entity: Post; id: 0x2a56c40 <x-coredata://9D07BF41-2DC0-42C1-9DD8-6082A00E7BEB/Post/p1> ; data: {\n    content = nil;\n    title = nil;\n    user = \"0x2af2a20 <x-coredata://9D07BF41-2DC0-42C1-9DD8-6082A00E7BEB/User/p1>\";\n})")
    
    <redacted> Predicate: objectID IN {0x2a56c40 <x-coredata://9D07BF41-2DC0-42C1-9DD8-6082A00E7BEB/Post/p1>} 
    
    <redacted> filteredRelationship: {(<Post: 0x2a04f10> (entity: Post; id: 0x2a56c40 <x-coredata://9D07BF41-2DC0-42C1-9DD8-6082A00E7BEB/Post/p1> ; data: { content = nil; title = nil; user = "0x2af2a20 <x-coredata://9D07BF41-2DC0-42C1-9DD8-6082A00E7BEB/User/p1>";}))}
    
    <redacted> fetchResult: ("<Post: 0x2a04f10> (entity: Post; id: 0x2a56c40 <x-coredata://9D07BF41-2DC0-42C1-9DD8-6082A00E7BEB/Post/p1> ; data: {\n    content = nil;\n    title = nil;\n    user = \"0x2af2a20 <x-coredata://9D07BF41-2DC0-42C1-9DD8-6082A00E7BEB/User/p1>\";\n})")
    

    【讨论】:

      【解决方案3】:

      Swift 3 解决方案

      我遇到了同样的情况,因此我在下面发布了一个 swift 3 解决方案

      let predicate = NSPredicate(format:"NOT (self IN %@)",[arrayofNSManagedObjects])
      

      【讨论】:

        猜你喜欢
        • 2013-08-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-02-07
        • 1970-01-01
        • 1970-01-01
        • 2015-12-24
        相关资源
        最近更新 更多