如何在NSPredicate中使用“ALL”聚合操作来过滤基于CoreData的集合
基于下面的数据模型
并基于用户input,我创build了一个名为selectedTags的实体标记的managedObjects的NSSet。
我的问题:
[NSPredicate predicateWithFormat:@"ANY entryTags IN %@", selectedTags];
…这将返回至less有一个EntryTag在SelectedTags集中的任何条目。
我想要的东西是:
[NSPredicate predicateWithFormat:@"ALL entryTags IN %@", selectedTags];
…注意唯一的变化是“任何”到“全部”。 这说明了我想要的,但不起作用。
为了制定我期望的结果:
我正在寻找一个解决scheme,将只返回入口的入口标签都在selectedTags列表(但在同一时间,如果可能的话,不一定是相反的方式)。
为了进一步说明:
(标签)的妈妈
(标签)爸爸
(标签)礼品
(进入)她是她…..(标签)妈妈
(进入)他是一个他……..(标签)爸爸
(进入)礼物给妈妈…(标签:)妈妈,礼物
(入门)爸爸的礼物…..(标签:)爸爸,礼物
如果selectedTags包含“妈妈”和“礼物”,那么“爸爸的礼物”将会出现,因为它有“礼物”的标签。 我宁愿它不显示:)
这是迄今为止确定的答案:
[NSPredicate predicateWithFormat:@"SUBQUERY(entryTags, $tag, $tag IN %@).@count = %d", selectedTags, [selectedTags count]];
美丽。
感谢Dave DeLong。
如何使用复合谓词? 据我所知,你想返回所有条目匹配的标签列表不只是其中的任何一个。 一种方法是为每个标签创build一个谓词,然后使用复合谓词将它们联系起来。
NSMutableArray *predicates = [[NSMutableArray alloc] init]; for (Tag *tag in selectedTags) { [predicates addObject:[NSPredicate predicateWithFormat:@"ANY entryTags.tagName MATCHES %@", tag.tagName]]; } NSPredicate *compoundPredicate = [NSCompoundPredicate andPredicateWithSubpredicates:predicates];
这应该达到你想要的。 然后,只需在请求中设置谓词。
你不能用谓词做你想要的。
ANY
和ALL
运算符适用于正在testing的实体(在本例中为Entry
),而不适用于集合( selectedTags
)的内容。 任何一个操作符都将返回一个与该集合中任何单个元素相匹配的Entry
对象。 ANY
运算符将返回find的第一个匹配项,而ALL
运算符将返回所有匹配项。 在任何情况下,他们都不会返回与提供的集合中的每个元素相匹配的条目。
(它也看起来像你正在试图在selectedTags
使用实际的Tag
对象,这很可能不起作用,因为没有专用比较方法的对象比较通常会失败,它也很慢,你需要比较谓词中的属性。
既然你已经有了你想要的Tag
对象,要find与候选相关的Entity
对象,你只需要走Tag.taggedEntries
关系。 然后,您必须find所有的Entity
对象集合的交集,才能find与每个选定的Tag
对象相关的Entity
对象。 由于没有相交的集合运算符,所以需要一个循环。
if ([selectedEntries count]>=2) { NSMutableSet *intersectEntries=[[NSMutableSet alloc] initWithCapacity:1]; for (int i=1; i<[selectedTags count]; i++) { if ([intersectEntries count]==0) { [intersectEntries unionSet:[[selectedEntries objectAtIndex:(i-1)] valueForKey:@"taggedEntries"]]; } [intersectEntries intersectSet:[[selectedEntries objectAtIndex:i] valueForKey:@"taggedEntries"]]; } }
(注:我没有testing这个,但它应该工作。)
现在intersectEntries
应该只包含那些与每个选定标签相关的Entry
对象。
我意识到我可以回到这里来获得我以前得到的指导。 通过使用TechZen提供的代码,我能够提出以下几点 – 对我来说,高度重视的一段代码:
- (NSArray *)unionSetOfObjectsForObjects:(NSArray *)objects { NSMutableSet *unionSetOfObjects = [NSMutableSet set]; if (objects.count) [unionSetOfObjects unionSet:[[objects objectAtIndex:0] valueForKey:@"key"]]; //unionSetOfObjects = [[objects objectAtIndex:0] valueForKey:@"key"]; if (objects.count > 1) for (id object in objects) [unionSetOfObjects intersectSet:[object valueForKey:@"key"]]; return unionSetOfObjects.allObjects; }
如果这个代码不是很明显的话:
它收集所有objects
数组中提供的所有对象上的键值(在我的大小写对象中)。
这个代码只是…味道不错,不是吗?
最简单的方法来做到这一点:
[NSPredicate predicateWithFormat:@"entryTags IN %@", selectedTags];
你不需要ALL子句。 这也logging在这里:
谓词编程指南
正如你可以在这篇文章中看到的,用户成功地做到了这一点(阅读原始问题的评论)
NSPredicate iPhone 3.2 SDK核心数据“IN子句”…
- Core Data父级ManagedObjectContext是否需要与子级上下文共享一个并发types?
- 使用NSPredicate按date过滤coredata不会返回任何内容
- NSPersistentStoreCoordinator在读取特定NSManagedProperty后释放NSManagedObject时抛出EXC_BAD_ACCESS
- 访问NSManagedObject的数据属性给我的内存问题
- 从Core Data存储创build.sqlite文件?
- 如何获取只是对象的ID,但也包括CoreData的行数据?
- 应用挂在__psynch_mutexwait
- 使核心数据线程安全
- 挂在NSManagedObjectContext的保存: