最近在看数据存储 Coredata 的内容,关于 coredata 不多叙述,网上挺多资料可以学习,不有一篇个人比较喜欢的博客链接,有兴趣的可以看一看,简洁明了,通俗易懂,很有自己的立场。
学习的过程中看到SUBQUERY子查询,相关的资料比较少,研究完总结一下,希望对有相同困扰的同学有帮助。
例子就照上面链接里的类。
有一个 Student 类,有属性 courses(修的课程,一对多,是一个集合NSSet ), age,name…
@interface Student : NSManagedObject
@property (nonatomic, retain) NSNumber * age;
@property (nonatomic, retain) NSString * name;
@property (nonatomic, retain) NSSet *courses;
现在有一个需求:要求筛选出所有选修了大学物理的学生。下面是相关代码
NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"Student" inManagedObjectContext:appContext];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entityDescription];
NSPredicate *filter = [NSPredicate predicateWithFormat:@"**SUBQUERY(courses, $course, $course.name == '大学物理').@count > 0**"];
[request setPredicate:filter];
NSError *error = nil;
NSArray *arrStudents = [appContext executeFetchRequest:request error:&error];
关于SUBQUERY,我觉得有两点需要搞懂
一:SUBQUERY结构:
SUBQUERY(collection_expression, variable_expression, predicate);
1.collection_expression:NSArray and NSSet或他俩的子集。此处就是 Student 对象里面的courses属性
2.variable_expression:SUBQUERY要遍历第一个参数集合,获取符合条件的对象。我们需要给集合里的每一个对象找一个名字代表,比如当我们用enumerateObjectsUsingBlock方法遍历数组时,用 obj 代表数组中的每一个元素,此处同理,我们可以用任何字符串来代表,course,c,x…都可以,此处我们用course来代表。完整的$course代表集合中的对象。当初我看这块就是在这里一脸懵逼的,完全不知道course是怎么来的。
3.predicate:这就是筛选的条件。
二:SUBQUERY().@count > 0
当初看这里也是懵了。@count大概猜到是一个求个数的函数。但是一度认为求得是上面代码里arrStudents的 count。其实这里 count 是指courses集合里符合筛选条件(科目是大学物理)的个数。对于 Student 表里的 student 对象,如果 student 对象的courses集合中科目是大学物理的 count > 0,该student 对象就会被加入arrStudents。
如下图:
整个例子可以这样理解。Student 表里有多个学生对象。每个学生对象有 name,age,courses 属性,其中 courses 是一个学科的集合。需求所有是找出修了大学物理的学生。即选出 Student 表中符合条件的 student 对象。对 student 对象里的courses属性进行遍历,如果courses里有元素的名字是‘大学物理’,并且count > 0,就把修了‘大学物理’的 student 添加到arrStudents。
参考链接:
http://blog.csdn.net/primer_programer/article/details/10102485
http://stackoverflow.com/questions/9630237/nspredicate-subquery-syntax