核心数据基于“有序”关系的属性进行提取

时间:2010-11-26 20:30:24

标签: core-data

我的应用程序具有类似功能的智能文件夹:谓词是使用NSPredicateEditor设置的,用于使用获取请求填充文件夹。

搜索中使用的实体具有多对多关系。在索引存储在目标实体中以进行排序的意义上,关系是有序的。

我的问题是我想基于有序关系中的最后一个值构建规则,但我无法弄清楚如何构建谓词来执行此操作,因为关系不是数组。核心数据实际上并不了解订单。

我在类上有一个readonly属性,它返回有序的项目,但这似乎对提取请求没有帮助,因为该属性在核心数据存储中不可用。

我能想到的唯一选择是对单独属性中订购的关系中的最后一项进行去规范化和存储。这是唯一的解决方案吗?

2 个答案:

答案 0 :(得分:2)

好吧,假设我已经正确理解了问题,我会这样做。假设你有两个实体,TopEntity有一个(NSString *)name属性和一个与MyEntity的to-many关系,它有一个(NSString *)数据属性和(NSInteger)顺序属性。

假设您想要匹配给定字符串的TopEntity对象,并且其MyEntity订单满足某个条件,那么您可以使用两个谓词和NSFetchRequest来执行此操作....

NSManagedObjectContext *context = [self managedObjectContext];

// Create some top level entities
TopEntity *aTop = [TopEntity insertInManagedObjectContext:context];
aTop.name = @"This is Your Name";
TopEntity *bTop = [TopEntity insertInManagedObjectContext:context];
bTop.name = @"This aint a Name";    
TopEntity *cTop = [TopEntity insertInManagedObjectContext:context];
cTop.name = @"This is My Name";    

// Add some data
NSInteger i, len = 30;
for(i=0; i<len; i++) {
    // Create a new object
    MyEntity *entity = [MyEntity insertInManagedObjectContext:context];
    entity.orderValue = i;
    entity.data = [NSString stringWithFormat:@"This is some data: %d", i];
    if(i < 10) {
        [aTop addObjectsObject:entity];
        [entity addTopObject:aTop];
    } else if (i < 20) {
        [bTop addObjectsObject:entity];
        [entity addTopObject:bTop];            
    } else {
        [cTop addObjectsObject:entity];
        [entity addTopObject:cTop];                        
    }
}

// Save the context
NSError *error = nil;
[context save:&error];

// A predicate to match against the top objects
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name BEGINSWITH %@", @"This is"];
// A predicate to match against the to-many objects
NSPredicate *secondPredicate = [NSPredicate predicateWithFormat:@"ANY objects.order < %d", 5];
NSFetchRequest *fetch = [[NSFetchRequest alloc] init];
[fetch setEntity:[NSEntityDescription entityForName:@"TopEntity" inManagedObjectContext:context]];
[fetch setPredicate:predicate];
NSArray *result = [[context executeFetchRequest:fetch error:&error] filteredArrayUsingPredicate:secondPredicate];


for(TopEntity *entity in result) {
    NSLog(@"entity name: %@", entity.name);         
}

因此,基本上你可以用另一个谓词包装你的获取请求的结果并使用ANY关键字。

我不知道它有多高效,但它适用于这种情况。运行上面的内容将输出“这是你的名字”,即它匹配第一个TopEntity。

答案 1 :(得分:1)

我认为只有在获取请求级别才能限制谓词中的 n 结果。

除了引用你提到的关系中的最后n个项目之外,你可以尝试一个布尔属性“lastN”并在你策划列表的顺序时打开/关闭它们(比如,在用户启动的排序或拖动期间) - 并且重新排序)。

或者,您可以为按排序键排序的每个搜索事物创建单独的获取请求,按降序排序,并限制(通过-setFetchLimit :)到 n 结果。

将此作为关系或属性进行跟踪有些“混乱”,而获取限制则更为昂贵(因为多次往返)。如果您的重新排序是通过一次性用户操作完成的,那么使用关系或属性方法可能会提高性能,因为工作是分摊的,而不是在一系列提取中一次性完成。我自己没有找到更好的方法,并会密切关注这一点。 : - )